[PATCH v2 4/6] arm/dt: mx51: dynamically add clocks per dt nodes

Shawn Guo shawn.guo at linaro.org
Sat Mar 19 05:24:30 EST 2011


This patch is to change the static clock creating and registering to
the dynamic way, which scans dt clock nodes, associate clk with
device_node, and then add them to clkdev accordingly.

It's a pretty straight translation from non-dt clock code to dt one,
and it does not really change any actual clock implementation.

Signed-off-by: Shawn Guo <shawn.guo at linaro.org>
---
 arch/arm/mach-mx5/Makefile          |    2 +-
 arch/arm/mach-mx5/clock-dt.c        |   52 --
 arch/arm/mach-mx5/clock-mx51-mx53.c | 1433 ++++++++++++++++++++++++++++++++++-
 3 files changed, 1410 insertions(+), 77 deletions(-)
 delete mode 100644 arch/arm/mach-mx5/clock-dt.c

diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index bd4542d..540697e 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -18,4 +18,4 @@ obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
 obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
 obj-$(CONFIG_MACH_MX50_RDP) += board-mx50_rdp.o
-obj-$(CONFIG_MACH_MX51_DT) += board-dt.o clock-dt.o
+obj-$(CONFIG_MACH_MX51_DT) += board-dt.o
diff --git a/arch/arm/mach-mx5/clock-dt.c b/arch/arm/mach-mx5/clock-dt.c
deleted file mode 100644
index 9c04475..0000000
--- a/arch/arm/mach-mx5/clock-dt.c
+++ /dev/null
@@ -1,52 +0,0 @@
-
-/*
- * Copyright 2011 Linaro Ltd.
- * Jason Liu <jason.hui at linaro.org>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_clk.h>
-
-static struct clk *mx5_dt_clk_get(struct device_node *np,
-					const char *output_id, void *data)
-{
-	return data;
-}
-
-static __init void mx5_dt_scan_clks(void)
-{
-	struct device_node *node;
-	struct clk *clk;
-	const char *id;
-	int rc;
-
-	for_each_compatible_node(node, NULL, "clock") {
-		id = of_get_property(node, "clock-outputs", NULL);
-		if (!id)
-			continue;
-
-		clk = clk_get_sys(id, NULL);
-		if (IS_ERR(clk))
-			continue;
-
-		rc = of_clk_add_provider(node, mx5_dt_clk_get, clk);
-		if (rc)
-			pr_err("error adding fixed clk %s\n", node->name);
-	}
-}
-
-void __init mx5_clk_dt_init(void)
-{
-	mx5_dt_scan_clks();
-}
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index 0a19e75..f5fdded 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -15,6 +15,10 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_clk.h>
 
 #include <asm/div64.h>
 
@@ -43,6 +47,28 @@ static struct clk emi_fast_clk;
 static struct clk ipu_clk;
 static struct clk mipi_hsc1_clk;
 
+/*
+ * The pointers are defined to unify the references to clocks, as clocks
+ * could also be created by dt code in a dynamic way besides the static
+ * way used in existing non-dt clock code.
+ */
+static struct clk *osc_clk_ptr;
+static struct clk *pll1_main_clk_ptr;
+static struct clk *pll1_sw_clk_ptr;
+static struct clk *pll2_sw_clk_ptr;
+static struct clk *pll3_sw_clk_ptr;
+static struct clk *lp_apm_clk_ptr;
+static struct clk *periph_apm_clk_ptr;
+static struct clk *main_bus_clk_ptr;
+static struct clk *ipg_clk_ptr;
+static struct clk *ipg_per_clk_ptr;
+static struct clk *cpu_clk_ptr;
+static struct clk *iim_clk_ptr;
+static struct clk *usboh3_clk_ptr;
+static struct clk *usb_phy1_clk_ptr;
+static struct clk *esdhc1_clk_ptr;
+static struct clk *esdhc2_clk_ptr;
+
 #define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
 
 /* calculate best pre and post dividers to get the required divider */
@@ -129,11 +155,11 @@ static inline u32 _get_mux(struct clk *parent, struct clk *m0,
 
 static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
 {
-	if (pll == &pll1_main_clk)
+	if (pll == pll1_main_clk_ptr)
 		return MX51_DPLL1_BASE;
-	else if (pll == &pll2_sw_clk)
+	else if (pll == pll2_sw_clk_ptr)
 		return MX51_DPLL2_BASE;
-	else if (pll == &pll3_sw_clk)
+	else if (pll == pll3_sw_clk_ptr)
 		return MX51_DPLL3_BASE;
 	else
 		BUG();
@@ -310,7 +336,7 @@ static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
 	 *
 	 * When switching back, do it in reverse order
 	 */
-	if (parent == &pll1_main_clk) {
+	if (parent == pll1_main_clk_ptr) {
 		/* Switch to pll1_main_clk */
 		reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
 		__raw_writel(reg, MXC_CCM_CCSR);
@@ -320,11 +346,11 @@ static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
 		reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
 				MXC_CCM_CCSR_STEP_SEL_OFFSET);
 	} else {
-		if (parent == &lp_apm_clk) {
+		if (parent == lp_apm_clk_ptr) {
 			step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
-		} else  if (parent == &pll2_sw_clk) {
+		} else  if (parent == pll2_sw_clk_ptr) {
 			step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
-		} else  if (parent == &pll3_sw_clk) {
+		} else  if (parent == pll3_sw_clk_ptr) {
 			step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
 		} else
 			return -EINVAL;
@@ -350,10 +376,10 @@ static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
 
 	reg = __raw_readl(MXC_CCM_CCSR);
 
-	if (clk->parent == &pll2_sw_clk) {
+	if (clk->parent == pll2_sw_clk_ptr) {
 		div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
 		       MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
-	} else if (clk->parent == &pll3_sw_clk) {
+	} else if (clk->parent == pll3_sw_clk_ptr) {
 		div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
 		       MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
 	} else
@@ -367,7 +393,7 @@ static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
 
 	reg = __raw_readl(MXC_CCM_CCSR);
 
-	if (parent == &pll2_sw_clk)
+	if (parent == pll2_sw_clk_ptr)
 		reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
 	else
 		reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
@@ -380,7 +406,7 @@ static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
 {
 	u32 reg;
 
-	if (parent == &osc_clk)
+	if (parent == osc_clk_ptr)
 		reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
 	else
 		return -EINVAL;
@@ -423,7 +449,8 @@ static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
 	u32 reg, mux;
 	int i = 0;
 
-	mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
+	mux = _get_mux(parent, pll1_sw_clk_ptr, pll3_sw_clk_ptr,
+			lp_apm_clk_ptr, NULL);
 
 	reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
 	reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
@@ -452,9 +479,9 @@ static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
 
 	reg = __raw_readl(MXC_CCM_CBCDR);
 
-	if (parent == &pll2_sw_clk)
+	if (parent == pll2_sw_clk_ptr)
 		reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
-	else if (parent == &periph_apm_clk)
+	else if (parent == periph_apm_clk_ptr)
 		reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
 	else
 		return -EINVAL;
@@ -587,7 +614,7 @@ static unsigned long clk_ipg_per_get_rate(struct clk *clk)
 
 	parent_rate = clk_get_rate(clk->parent);
 
-	if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
+	if (clk->parent == main_bus_clk_ptr || clk->parent == lp_apm_clk_ptr) {
 		/* the main_bus_clk is the one before the DVFS engine */
 		reg = __raw_readl(MXC_CCM_CBCDR);
 		prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
@@ -597,7 +624,7 @@ static unsigned long clk_ipg_per_get_rate(struct clk *clk)
 		podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
 			MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
 		return parent_rate / (prediv1 * prediv2 * podf);
-	} else if (clk->parent == &ipg_clk)
+	} else if (clk->parent == ipg_clk_ptr)
 		return parent_rate;
 	else
 		BUG();
@@ -612,11 +639,11 @@ static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
 	reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
 	reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
 
-	if (parent == &ipg_clk)
+	if (parent == ipg_clk_ptr)
 		reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
-	else if (parent == &lp_apm_clk)
+	else if (parent == lp_apm_clk_ptr)
 		reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
-	else if (parent != &main_bus_clk)
+	else if (parent != main_bus_clk_ptr)
 		return -EINVAL;
 
 	__raw_writel(reg, MXC_CCM_CBCMR);
@@ -830,7 +857,7 @@ static struct clk ipg_clk = {
 	.get_rate = clk_ipg_get_rate,
 };
 
-static struct clk ipg_perclk = {
+static struct clk ipg_per_clk = {
 	.parent = &lp_apm_clk,
 	.get_rate = clk_ipg_per_get_rate,
 	.set_parent = _clk_ipg_per_set_parent,
@@ -1036,8 +1063,9 @@ static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)	\
 {									\
 	u32 reg, mux;							\
 									\
-	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,		\
-			&pll3_sw_clk, &lp_apm_clk);			\
+	mux = _get_mux(parent, pll1_sw_clk_ptr, pll2_sw_clk_ptr,	\
+			pll3_sw_clk_ptr, lp_apm_clk_ptr);		\
+									\
 	reg = __raw_readl(MXC_CCM_CSCMR##nr) &				\
 		~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK;		\
 	reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET;	\
@@ -1115,7 +1143,7 @@ static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
 
 	reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
 
-	if (parent == &pll3_sw_clk)
+	if (parent == pll3_sw_clk_ptr)
 		reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
 
 	__raw_writel(reg, MXC_CCM_CSCMR1);
@@ -1346,7 +1374,7 @@ static void clk_tree_init(void)
 {
 	u32 reg;
 
-	ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
+	clk_set_parent(ipg_per_clk_ptr, lp_apm_clk_ptr);
 
 	/*
 	 * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
@@ -1367,6 +1395,27 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
 {
 	int i;
 
+	/*
+	 * Save the clock pointers that could be referenced by
+	 * both non-dt and dt clock codes later in this file.
+	 */
+	osc_clk_ptr		= &osc_clk;
+	pll1_main_clk_ptr	= &pll1_main_clk;
+	pll1_sw_clk_ptr		= &pll1_sw_clk;
+	pll2_sw_clk_ptr		= &pll2_sw_clk;
+	pll3_sw_clk_ptr		= &pll3_sw_clk;
+	lp_apm_clk_ptr		= &lp_apm_clk;
+	periph_apm_clk_ptr	= &periph_apm_clk;
+	main_bus_clk_ptr	= &main_bus_clk;
+	ipg_clk_ptr		= &ipg_clk;
+	ipg_per_clk_ptr		= &ipg_per_clk;
+	cpu_clk_ptr		= &cpu_clk;
+	iim_clk_ptr		= &iim_clk;
+	usboh3_clk_ptr		= &usboh3_clk;
+	usb_phy1_clk_ptr	= &usb_phy1_clk;
+	esdhc1_clk_ptr		= &esdhc1_clk;
+	esdhc2_clk_ptr		= &esdhc2_clk;
+
 	external_low_reference = ckil;
 	external_high_reference = ckih1;
 	ckih2_reference = ckih2;
@@ -1432,3 +1481,1339 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
 		MX53_INT_GPT);
 	return 0;
 }
+
+/*
+ * Dynamically create and register clks per dt nodes
+ */
+#ifdef CONFIG_OF
+static unsigned long get_fixed_clk_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+static __init int mx5_scan_fixed_clks(void)
+{
+	struct device_node *node;
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *rate;
+	const char *dev_id;
+	int ret = 0;
+
+	for_each_compatible_node(node, NULL, "fixed-clock") {
+		cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL);
+		if (!cl) {
+			ret = -ENOMEM;
+			break;
+		}
+		clk = (struct clk *) (cl + 1);
+
+		dev_id = of_get_property(node, "clock-outputs", NULL);
+		if (!dev_id) {
+			kfree(cl);
+			continue;
+		}
+
+		rate = of_get_property(node, "clock-frequency", NULL);
+		if (!rate) {
+			kfree(cl);
+			continue;
+		}
+		clk->rate = be32_to_cpu(*rate);
+		clk->get_rate = get_fixed_clk_rate;
+
+		if (!strcmp(node->name, "osc"))
+			osc_clk_ptr = clk;
+
+		node->clk = clk;
+
+		cl->dev_id = dev_id;
+		cl->clk = clk;
+		clkdev_add(cl);
+	}
+
+	return ret;
+}
+
+static struct clk *mx5_prop_name_to_clk(struct device_node *node,
+		const char *prop_name)
+{
+	struct device_node *provnode;
+	struct clk *clk;
+	const void *prop;
+	u32 provhandle;
+	int sz;
+
+	prop = of_get_property(node, prop_name, &sz);
+	if (!prop || sz < 4)
+		goto out;
+
+	/* Extract the phandle from the start of the property value */
+	provhandle = be32_to_cpup(prop);
+	prop += 4;
+	sz -= 4;
+
+	/*
+	 * Make sure the clock name is properly terminated and within the
+	 * size of the property.
+	 */
+	if (strlen(prop) + 1 > sz)
+		goto out;
+
+	provnode = of_find_node_by_phandle(provhandle);
+	if (!provnode)
+		goto out;
+
+	clk = provnode->clk;
+
+	of_node_put(provnode);
+
+	return clk;
+
+out:
+	pr_err("%s: failed to get %s of %s\n", __func__, prop_name, node->name);
+	return NULL;
+}
+
+static inline struct clk *mx5_get_source_clk(struct device_node *node)
+{
+	return mx5_prop_name_to_clk(node, "src-clock");
+}
+
+static inline struct clk *mx5_get_depend_clk(struct device_node *node)
+{
+	return mx5_prop_name_to_clk(node, "dep-clock");
+}
+
+static __init struct clk_lookup *mx5_pre_clk_lookup(struct device_node * node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL);
+	if (cl) {
+		clk = (struct clk *) (cl + 1);
+		clk->parent = mx5_get_source_clk(node);
+		clk->secondary = mx5_get_source_clk(node);
+	}
+
+	return cl;
+}
+
+static __init int mx5_post_clk_lookup(struct clk_lookup *cl,
+				      struct device_node *node)
+{
+	struct clk *clk;
+	const char *dev_id;
+
+	dev_id = of_get_property(node, "clock-outputs", NULL);
+	if (!dev_id) {
+		kfree(cl);
+		return -EINVAL;
+	}
+
+	clk = (struct clk *) (cl + 1);
+	node->clk = clk;
+
+	cl->dev_id = dev_id;
+	cl->clk = clk;
+	clkdev_add(cl);
+
+	return 0;
+}
+
+static __init int mx5_add_dummy_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = kzalloc(sizeof(*cl) + sizeof(*clk), GFP_KERNEL);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	node->clk = clk;
+
+	cl->clk = clk;
+	clkdev_add(cl);
+
+	return 0;
+}
+
+static __init int mx5_add_usb_phy1_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG0_OFFSET;
+	clk->set_parent = clk_usb_phy1_set_parent;
+
+	usb_phy1_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_usb_ahb_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG13_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_usboh3_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_usboh3_get_rate;
+	clk->set_parent = clk_usboh3_set_parent;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG14_OFFSET;
+
+	usboh3_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_mipi_hsp_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_hsc_enable;
+	clk->disable = _clk_hsc_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG6_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipu_di_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR6;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG5_OFFSET :
+					MXC_CCM_CCGRx_CG6_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipu_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = clk_ipu_enable;
+	clk->disable = clk_ipu_disable;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipu_sec_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_mipi_hsc_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG3_OFFSET :
+					MXC_CCM_CCGRx_CG4_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_mipi_esc_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_esdhc_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_max_enable;
+	clk->disable = _clk_max_disable;
+	clk->enable_reg = MXC_CCM_CCGR3;
+
+	if (id == 0) {
+		clk->enable_shift = MXC_CCM_CCGRx_CG1_OFFSET;
+		clk->get_rate = clk_esdhc1_get_rate;
+		clk->set_rate = clk_esdhc1_set_rate;
+		clk->set_parent = clk_esdhc1_set_parent;
+		esdhc1_clk_ptr = clk;
+	} else {
+		clk->enable_shift = MXC_CCM_CCGRx_CG3_OFFSET;
+		clk->get_rate = clk_esdhc2_get_rate;
+		clk->set_rate = clk_esdhc2_set_rate;
+		clk->set_parent = clk_esdhc2_set_parent;
+		esdhc2_clk_ptr = clk;
+	}
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_esdhc_ipg_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_max_enable;
+	clk->disable = _clk_max_disable;
+	clk->enable_reg = MXC_CCM_CCGR3;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG0_OFFSET :
+					MXC_CCM_CCGRx_CG2_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_sdma_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG15_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ecspi_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG10_OFFSET :
+					MXC_CCM_CCGRx_CG12_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ecspi_ipg_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable_inrun;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG9_OFFSET :
+					MXC_CCM_CCGRx_CG11_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ecspi_main_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_ecspi_get_rate;
+	clk->set_parent = clk_ecspi_set_parent;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_cspi_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG13_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_cspi_ipg_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR4;
+	clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ssi_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR3;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG11_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG13_OFFSET;
+	}
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ssi_ipg_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR3;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG12_OFFSET;
+	}
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_nfc_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
+	clk->get_rate = clk_nfc_get_rate;
+	clk->set_rate = clk_nfc_set_rate;
+	clk->round_rate = clk_nfc_round_rate;
+	clk->set_parent = clk_nfc_set_parent;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_i2c_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR1;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG11_OFFSET;
+	}
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_pwm_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG6_OFFSET :
+					MXC_CCM_CCGRx_CG8_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_fec_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG12_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_uart_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR1;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG4_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG6_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
+	}
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_uart_root_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_uart_get_rate;
+	clk->set_parent = clk_uart_set_parent;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_uart_ipg_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR1;
+
+	switch (id) {
+	case 0:
+		clk->enable_shift = MXC_CCM_CCGRx_CG3_OFFSET;
+		break;
+	case 1:
+		clk->enable_shift = MXC_CCM_CCGRx_CG5_OFFSET;
+		break;
+	case 2:
+		clk->enable_shift = MXC_CCM_CCGRx_CG7_OFFSET;
+	}
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_gpt_32k_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_gpt_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG9_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_gpt_ipg_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR2;
+	clk->enable_shift = MXC_CCM_CCGRx_CG10_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ahbmux1_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable_inwait;
+	clk->enable_reg = MXC_CCM_CCGR0;
+	clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_aips_tz_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 1)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable_inwait;
+	clk->enable_reg = MXC_CCM_CCGR0;
+	clk->enable_shift = (id == 0) ? MXC_CCM_CCGRx_CG12_OFFSET :
+					MXC_CCM_CCGRx_CG13_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ahb_max_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_max_enable;
+	clk->disable = _clk_max_disable;
+	clk->enable_reg = MXC_CCM_CCGR0;
+	clk->enable_shift = MXC_CCM_CCGRx_CG14_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_iim_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable_reg = MXC_CCM_CCGR0;
+	clk->enable_shift = MXC_CCM_CCGRx_CG15_OFFSET;
+
+	iim_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_spba_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG0_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipg_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_ipg_get_rate;
+
+	ipg_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ahb_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_ahb_get_rate;
+	clk->set_rate = _clk_ahb_set_rate;
+	clk->round_rate = _clk_ahb_round_rate;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_emi_slow_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable_inwait;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG8_OFFSET;
+	clk->get_rate = clk_emi_slow_get_rate;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_main_bus_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->set_parent = _clk_main_bus_set_parent;
+
+	main_bus_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_emi_fast_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->enable = _clk_ccgr_enable;
+	clk->disable = _clk_ccgr_disable_inwait;
+	clk->enable_reg = MXC_CCM_CCGR5;
+	clk->enable_shift = MXC_CCM_CCGRx_CG7_OFFSET;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ddr_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ddr_hf_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = _clk_ddr_hf_get_rate;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_cpu_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_cpu_get_rate;
+	clk->set_rate = clk_cpu_set_rate;
+
+	cpu_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_ipg_per_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_ipg_per_get_rate;
+	clk->set_parent = _clk_ipg_per_set_parent;
+
+	ipg_per_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_periph_apm_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->set_parent = _clk_periph_apm_set_parent;
+
+	periph_apm_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_lp_apm_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->set_parent = _clk_lp_apm_set_parent;
+
+	lp_apm_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_pll_switch_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+	const __be32 *reg;
+	int id;
+
+	reg = of_get_property(node, "reg", NULL);
+	if (!reg)
+		return -ENOENT;
+
+	id = be32_to_cpu(*reg);
+	if (id < 0 || id > 2)
+		return -EINVAL;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->id = id;
+
+	switch (id) {
+	case 0:
+		clk->get_rate = clk_pll1_sw_get_rate;
+		clk->set_parent = _clk_pll1_sw_set_parent;
+		pll1_sw_clk_ptr = clk;
+		break;
+	case 1:
+		clk->get_rate = clk_pll_get_rate;
+		clk->set_rate = _clk_pll_set_rate;
+		clk->enable = _clk_pll_enable;
+		clk->disable = _clk_pll_disable;
+		clk->set_parent = _clk_pll2_sw_set_parent;
+		pll2_sw_clk_ptr = clk;
+		break;
+	case 2:
+		clk->get_rate = clk_pll_get_rate;
+		clk->set_rate = _clk_pll_set_rate;
+		clk->enable = _clk_pll_enable;
+		clk->disable = _clk_pll_disable;
+		pll3_sw_clk_ptr = clk;
+	}
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+static __init int mx5_add_pll1_main_clk(struct device_node *node)
+{
+	struct clk_lookup *cl;
+	struct clk *clk;
+
+	cl = mx5_pre_clk_lookup(node);
+	if (!cl)
+		return -ENOMEM;
+	clk = (struct clk *) (cl + 1);
+
+	clk->get_rate = clk_pll_get_rate;
+	clk->enable = _clk_pll_enable;
+	clk->disable = _clk_pll_disable;
+
+	pll1_main_clk_ptr = clk;
+
+	return mx5_post_clk_lookup(cl, node);
+}
+
+#define MX5_CLK_COMP	"fsl,mxc-clock"
+
+static const struct of_device_id mx5_dt_mxc_clock_ids[] = {
+	{ .name = "pll1_main",	.compatible = MX5_CLK_COMP, .data = mx5_add_pll1_main_clk },
+	{ .name = "pll_switch", .compatible = MX5_CLK_COMP, .data = mx5_add_pll_switch_clk },
+	{ .name = "lp_apm",	.compatible = MX5_CLK_COMP, .data = mx5_add_lp_apm_clk },
+	{ .name = "periph_apm", .compatible = MX5_CLK_COMP, .data = mx5_add_periph_apm_clk },
+	{ .name = "ipg_per",	.compatible = MX5_CLK_COMP, .data = mx5_add_ipg_per_clk },
+	{ .name = "cpu",	.compatible = MX5_CLK_COMP, .data = mx5_add_cpu_clk },
+	{ .name = "ddr_hf",	.compatible = MX5_CLK_COMP, .data = mx5_add_ddr_hf_clk },
+	{ .name = "ddr",	.compatible = MX5_CLK_COMP, .data = mx5_add_ddr_clk },
+	{ .name = "emi_fast",	.compatible = MX5_CLK_COMP, .data = mx5_add_emi_fast_clk },
+	{ .name = "main_bus",	.compatible = MX5_CLK_COMP, .data = mx5_add_main_bus_clk },
+	{ .name = "emi_slow",	.compatible = MX5_CLK_COMP, .data = mx5_add_emi_slow_clk },
+	{ .name = "ahb",	.compatible = MX5_CLK_COMP, .data = mx5_add_ahb_clk },
+	{ .name = "ipg",	.compatible = MX5_CLK_COMP, .data = mx5_add_ipg_clk },
+	{ .name = "spba",	.compatible = MX5_CLK_COMP, .data = mx5_add_spba_clk },
+	{ .name = "iim",	.compatible = MX5_CLK_COMP, .data = mx5_add_iim_clk },
+	{ .name = "ahb_max",	.compatible = MX5_CLK_COMP, .data = mx5_add_ahb_max_clk },
+	{ .name = "aips_tz",	.compatible = MX5_CLK_COMP, .data = mx5_add_aips_tz_clk },
+	{ .name = "ahbmux1",	.compatible = MX5_CLK_COMP, .data = mx5_add_ahbmux1_clk },
+	{ .name = "gpt_ipg",	.compatible = MX5_CLK_COMP, .data = mx5_add_gpt_ipg_clk },
+	{ .name = "gpt",	.compatible = MX5_CLK_COMP, .data = mx5_add_gpt_clk },
+	{ .name = "gpt_32k",	.compatible = MX5_CLK_COMP, .data = mx5_add_gpt_32k_clk },
+	{ .name = "uart_ipg",	.compatible = MX5_CLK_COMP, .data = mx5_add_uart_ipg_clk },
+	{ .name = "uart_root",	.compatible = MX5_CLK_COMP, .data = mx5_add_uart_root_clk },
+	{ .name = "uart",	.compatible = MX5_CLK_COMP, .data = mx5_add_uart_clk },
+	{ .name = "fec",	.compatible = MX5_CLK_COMP, .data = mx5_add_fec_clk },
+	{ .name = "pwm",	.compatible = MX5_CLK_COMP, .data = mx5_add_pwm_clk },
+	{ .name = "i2c",	.compatible = MX5_CLK_COMP, .data = mx5_add_i2c_clk },
+	{ .name = "nfc",	.compatible = MX5_CLK_COMP, .data = mx5_add_nfc_clk },
+	{ .name = "ssi_ipg",	.compatible = MX5_CLK_COMP, .data = mx5_add_ssi_ipg_clk },
+	{ .name = "ssi",	.compatible = MX5_CLK_COMP, .data = mx5_add_ssi_clk },
+	{ .name = "cspi_ipg",	.compatible = MX5_CLK_COMP, .data = mx5_add_cspi_ipg_clk },
+	{ .name = "cspi",	.compatible = MX5_CLK_COMP, .data = mx5_add_cspi_clk },
+	{ .name = "ecspi_main",	.compatible = MX5_CLK_COMP, .data = mx5_add_ecspi_main_clk },
+	{ .name = "ecspi_ipg",	.compatible = MX5_CLK_COMP, .data = mx5_add_ecspi_ipg_clk },
+	{ .name = "ecspi",	.compatible = MX5_CLK_COMP, .data = mx5_add_ecspi_clk },
+	{ .name = "sdma",	.compatible = MX5_CLK_COMP, .data = mx5_add_sdma_clk },
+	{ .name = "esdhc_ipg",	.compatible = MX5_CLK_COMP, .data = mx5_add_esdhc_ipg_clk },
+	{ .name = "esdhc",	.compatible = MX5_CLK_COMP, .data = mx5_add_esdhc_clk },
+	{ .name = "mipi_esc",	.compatible = MX5_CLK_COMP, .data = mx5_add_mipi_esc_clk },
+	{ .name = "mipi_hsc",	.compatible = MX5_CLK_COMP, .data = mx5_add_mipi_hsc_clk },
+	{ .name = "ipu_sec",	.compatible = MX5_CLK_COMP, .data = mx5_add_ipu_sec_clk },
+	{ .name = "ipu",	.compatible = MX5_CLK_COMP, .data = mx5_add_ipu_clk },
+	{ .name = "ipu_di",	.compatible = MX5_CLK_COMP, .data = mx5_add_ipu_di_clk },
+	{ .name = "mipi_hsp",	.compatible = MX5_CLK_COMP, .data = mx5_add_mipi_hsp_clk },
+	{ .name = "usboh3",	.compatible = MX5_CLK_COMP, .data = mx5_add_usboh3_clk },
+	{ .name = "usb_ahb",	.compatible = MX5_CLK_COMP, .data = mx5_add_usb_ahb_clk },
+	{ .name = "usb_phy1",	.compatible = MX5_CLK_COMP, .data = mx5_add_usb_phy1_clk },
+	{ .name = "dummy",	.compatible = MX5_CLK_COMP, .data = mx5_add_dummy_clk },
+	{ /* sentinel */ }
+};
+
+static __init int mx5_dt_scan_clks(void)
+{
+	struct device_node *np;
+	const struct of_device_id *dt_clk_id;
+	int (*mx5_add_clk)(struct device_node *);
+	int ret;
+
+	ret = mx5_scan_fixed_clks();
+	if (ret) {
+		pr_err("%s: fixed-clock failed %d\n", __func__, ret);
+		return ret;
+	}
+
+	for_each_matching_node(np, mx5_dt_mxc_clock_ids) {
+		dt_clk_id = of_match_node(mx5_dt_mxc_clock_ids, np);
+		mx5_add_clk = dt_clk_id->data;
+		ret = mx5_add_clk(np);
+		if (ret) {
+			pr_err("%s: clock %s failed %d\n",
+				__func__, np->name, ret);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+void __init mx5_clk_dt_init(void)
+{
+	mx5_dt_scan_clks();
+
+	clk_tree_init();
+
+	clk_enable(cpu_clk_ptr);
+	clk_enable(main_bus_clk_ptr);
+
+	clk_enable(iim_clk_ptr);
+	mx51_revision();
+	clk_disable(iim_clk_ptr);
+
+	/* move usb_phy_clk to 24MHz */
+	clk_set_parent(usb_phy1_clk_ptr, osc_clk_ptr);
+
+	/* set the usboh3_clk parent to pll2_sw_clk */
+	clk_set_parent(usboh3_clk_ptr, pll2_sw_clk_ptr);
+
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(esdhc1_clk_ptr, pll2_sw_clk_ptr);
+	clk_set_parent(esdhc2_clk_ptr, pll2_sw_clk_ptr);
+
+	/* set SDHC root clock as 166.25MHZ*/
+	clk_set_rate(esdhc1_clk_ptr, 166250000);
+	clk_set_rate(esdhc2_clk_ptr, 166250000);
+}
+#endif
-- 
1.7.1



More information about the devicetree-discuss mailing list