From d6968fca789700afd723347d9d583795b19224b8 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Thu, 30 Apr 2015 13:54:13 -0700
Subject: [PATCH 001/135] clk: s/clk/core/ for struct clk_core

While introducing struct clk_core we tried to minimize the diff
by changing the type of 'clk' variables from struct clk to struct
clk_core without changing the names of the variables. Now that
the split is complete, the code is slightly confusing when it
mixes variables called 'clk' and variables called 'core' that are
of the same type struct clk_core. Let's be consistent and use
'core' everywhere we have a struct clk_core pointer and 'clk'
when we have a struct clk pointer.

Cc: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 824 +++++++++++++++++++++++-----------------------
 1 file changed, 412 insertions(+), 412 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 459ce9da13e0..0b3c914db1ca 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -37,11 +37,11 @@ static HLIST_HEAD(clk_root_list);
 static HLIST_HEAD(clk_orphan_list);
 static LIST_HEAD(clk_notifier_list);
 
-static long clk_core_get_accuracy(struct clk_core *clk);
-static unsigned long clk_core_get_rate(struct clk_core *clk);
-static int clk_core_get_phase(struct clk_core *clk);
-static bool clk_core_is_prepared(struct clk_core *clk);
-static bool clk_core_is_enabled(struct clk_core *clk);
+static long clk_core_get_accuracy(struct clk_core *core);
+static unsigned long clk_core_get_rate(struct clk_core *core);
+static int clk_core_get_phase(struct clk_core *core);
+static bool clk_core_is_prepared(struct clk_core *core);
+static bool clk_core_is_enabled(struct clk_core *core);
 static struct clk_core *clk_core_lookup(const char *name);
 
 /***    private data structures    ***/
@@ -293,59 +293,59 @@ static const struct file_operations clk_dump_fops = {
 	.release	= single_release,
 };
 
-static int clk_debug_create_one(struct clk_core *clk, struct dentry *pdentry)
+static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
 {
 	struct dentry *d;
 	int ret = -ENOMEM;
 
-	if (!clk || !pdentry) {
+	if (!core || !pdentry) {
 		ret = -EINVAL;
 		goto out;
 	}
 
-	d = debugfs_create_dir(clk->name, pdentry);
+	d = debugfs_create_dir(core->name, pdentry);
 	if (!d)
 		goto out;
 
-	clk->dentry = d;
+	core->dentry = d;
 
-	d = debugfs_create_u32("clk_rate", S_IRUGO, clk->dentry,
-			(u32 *)&clk->rate);
+	d = debugfs_create_u32("clk_rate", S_IRUGO, core->dentry,
+			(u32 *)&core->rate);
 	if (!d)
 		goto err_out;
 
-	d = debugfs_create_u32("clk_accuracy", S_IRUGO, clk->dentry,
-			(u32 *)&clk->accuracy);
+	d = debugfs_create_u32("clk_accuracy", S_IRUGO, core->dentry,
+			(u32 *)&core->accuracy);
 	if (!d)
 		goto err_out;
 
-	d = debugfs_create_u32("clk_phase", S_IRUGO, clk->dentry,
-			(u32 *)&clk->phase);
+	d = debugfs_create_u32("clk_phase", S_IRUGO, core->dentry,
+			(u32 *)&core->phase);
 	if (!d)
 		goto err_out;
 
-	d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
-			(u32 *)&clk->flags);
+	d = debugfs_create_x32("clk_flags", S_IRUGO, core->dentry,
+			(u32 *)&core->flags);
 	if (!d)
 		goto err_out;
 
-	d = debugfs_create_u32("clk_prepare_count", S_IRUGO, clk->dentry,
-			(u32 *)&clk->prepare_count);
+	d = debugfs_create_u32("clk_prepare_count", S_IRUGO, core->dentry,
+			(u32 *)&core->prepare_count);
 	if (!d)
 		goto err_out;
 
-	d = debugfs_create_u32("clk_enable_count", S_IRUGO, clk->dentry,
-			(u32 *)&clk->enable_count);
+	d = debugfs_create_u32("clk_enable_count", S_IRUGO, core->dentry,
+			(u32 *)&core->enable_count);
 	if (!d)
 		goto err_out;
 
-	d = debugfs_create_u32("clk_notifier_count", S_IRUGO, clk->dentry,
-			(u32 *)&clk->notifier_count);
+	d = debugfs_create_u32("clk_notifier_count", S_IRUGO, core->dentry,
+			(u32 *)&core->notifier_count);
 	if (!d)
 		goto err_out;
 
-	if (clk->ops->debug_init) {
-		ret = clk->ops->debug_init(clk->hw, clk->dentry);
+	if (core->ops->debug_init) {
+		ret = core->ops->debug_init(core->hw, core->dentry);
 		if (ret)
 			goto err_out;
 	}
@@ -354,31 +354,31 @@ static int clk_debug_create_one(struct clk_core *clk, struct dentry *pdentry)
 	goto out;
 
 err_out:
-	debugfs_remove_recursive(clk->dentry);
-	clk->dentry = NULL;
+	debugfs_remove_recursive(core->dentry);
+	core->dentry = NULL;
 out:
 	return ret;
 }
 
 /**
  * clk_debug_register - add a clk node to the debugfs clk tree
- * @clk: the clk being added to the debugfs clk tree
+ * @core: the clk being added to the debugfs clk tree
  *
  * Dynamically adds a clk to the debugfs clk tree if debugfs has been
  * initialized.  Otherwise it bails out early since the debugfs clk tree
  * will be created lazily by clk_debug_init as part of a late_initcall.
  */
-static int clk_debug_register(struct clk_core *clk)
+static int clk_debug_register(struct clk_core *core)
 {
 	int ret = 0;
 
 	mutex_lock(&clk_debug_lock);
-	hlist_add_head(&clk->debug_node, &clk_debug_list);
+	hlist_add_head(&core->debug_node, &clk_debug_list);
 
 	if (!inited)
 		goto unlock;
 
-	ret = clk_debug_create_one(clk, rootdir);
+	ret = clk_debug_create_one(core, rootdir);
 unlock:
 	mutex_unlock(&clk_debug_lock);
 
@@ -387,18 +387,18 @@ unlock:
 
  /**
  * clk_debug_unregister - remove a clk node from the debugfs clk tree
- * @clk: the clk being removed from the debugfs clk tree
+ * @core: the clk being removed from the debugfs clk tree
  *
  * Dynamically removes a clk and all it's children clk nodes from the
  * debugfs clk tree if clk->dentry points to debugfs created by
  * clk_debug_register in __clk_init.
  */
-static void clk_debug_unregister(struct clk_core *clk)
+static void clk_debug_unregister(struct clk_core *core)
 {
 	mutex_lock(&clk_debug_lock);
-	hlist_del_init(&clk->debug_node);
-	debugfs_remove_recursive(clk->dentry);
-	clk->dentry = NULL;
+	hlist_del_init(&core->debug_node);
+	debugfs_remove_recursive(core->dentry);
+	core->dentry = NULL;
 	mutex_unlock(&clk_debug_lock);
 }
 
@@ -429,7 +429,7 @@ EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
  */
 static int __init clk_debug_init(void)
 {
-	struct clk_core *clk;
+	struct clk_core *core;
 	struct dentry *d;
 
 	rootdir = debugfs_create_dir("clk", NULL);
@@ -458,8 +458,8 @@ static int __init clk_debug_init(void)
 		return -ENOMEM;
 
 	mutex_lock(&clk_debug_lock);
-	hlist_for_each_entry(clk, &clk_debug_list, debug_node)
-		clk_debug_create_one(clk, rootdir);
+	hlist_for_each_entry(core, &clk_debug_list, debug_node)
+		clk_debug_create_one(core, rootdir);
 
 	inited = 1;
 	mutex_unlock(&clk_debug_lock);
@@ -468,59 +468,59 @@ static int __init clk_debug_init(void)
 }
 late_initcall(clk_debug_init);
 #else
-static inline int clk_debug_register(struct clk_core *clk) { return 0; }
-static inline void clk_debug_reparent(struct clk_core *clk,
+static inline int clk_debug_register(struct clk_core *core) { return 0; }
+static inline void clk_debug_reparent(struct clk_core *core,
 				      struct clk_core *new_parent)
 {
 }
-static inline void clk_debug_unregister(struct clk_core *clk)
+static inline void clk_debug_unregister(struct clk_core *core)
 {
 }
 #endif
 
 /* caller must hold prepare_lock */
-static void clk_unprepare_unused_subtree(struct clk_core *clk)
+static void clk_unprepare_unused_subtree(struct clk_core *core)
 {
 	struct clk_core *child;
 
 	lockdep_assert_held(&prepare_lock);
 
-	hlist_for_each_entry(child, &clk->children, child_node)
+	hlist_for_each_entry(child, &core->children, child_node)
 		clk_unprepare_unused_subtree(child);
 
-	if (clk->prepare_count)
+	if (core->prepare_count)
 		return;
 
-	if (clk->flags & CLK_IGNORE_UNUSED)
+	if (core->flags & CLK_IGNORE_UNUSED)
 		return;
 
-	if (clk_core_is_prepared(clk)) {
-		trace_clk_unprepare(clk);
-		if (clk->ops->unprepare_unused)
-			clk->ops->unprepare_unused(clk->hw);
-		else if (clk->ops->unprepare)
-			clk->ops->unprepare(clk->hw);
-		trace_clk_unprepare_complete(clk);
+	if (clk_core_is_prepared(core)) {
+		trace_clk_unprepare(core);
+		if (core->ops->unprepare_unused)
+			core->ops->unprepare_unused(core->hw);
+		else if (core->ops->unprepare)
+			core->ops->unprepare(core->hw);
+		trace_clk_unprepare_complete(core);
 	}
 }
 
 /* caller must hold prepare_lock */
-static void clk_disable_unused_subtree(struct clk_core *clk)
+static void clk_disable_unused_subtree(struct clk_core *core)
 {
 	struct clk_core *child;
 	unsigned long flags;
 
 	lockdep_assert_held(&prepare_lock);
 
-	hlist_for_each_entry(child, &clk->children, child_node)
+	hlist_for_each_entry(child, &core->children, child_node)
 		clk_disable_unused_subtree(child);
 
 	flags = clk_enable_lock();
 
-	if (clk->enable_count)
+	if (core->enable_count)
 		goto unlock_out;
 
-	if (clk->flags & CLK_IGNORE_UNUSED)
+	if (core->flags & CLK_IGNORE_UNUSED)
 		goto unlock_out;
 
 	/*
@@ -528,13 +528,13 @@ static void clk_disable_unused_subtree(struct clk_core *clk)
 	 * sequence.  call .disable_unused if available, otherwise fall
 	 * back to .disable
 	 */
-	if (clk_core_is_enabled(clk)) {
-		trace_clk_disable(clk);
-		if (clk->ops->disable_unused)
-			clk->ops->disable_unused(clk->hw);
-		else if (clk->ops->disable)
-			clk->ops->disable(clk->hw);
-		trace_clk_disable_complete(clk);
+	if (clk_core_is_enabled(core)) {
+		trace_clk_disable(core);
+		if (core->ops->disable_unused)
+			core->ops->disable_unused(core->hw);
+		else if (core->ops->disable)
+			core->ops->disable(core->hw);
+		trace_clk_disable_complete(core);
 	}
 
 unlock_out:
@@ -551,7 +551,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup);
 
 static int clk_disable_unused(void)
 {
-	struct clk_core *clk;
+	struct clk_core *core;
 
 	if (clk_ignore_unused) {
 		pr_warn("clk: Not disabling unused clocks\n");
@@ -560,17 +560,17 @@ static int clk_disable_unused(void)
 
 	clk_prepare_lock();
 
-	hlist_for_each_entry(clk, &clk_root_list, child_node)
-		clk_disable_unused_subtree(clk);
+	hlist_for_each_entry(core, &clk_root_list, child_node)
+		clk_disable_unused_subtree(core);
 
-	hlist_for_each_entry(clk, &clk_orphan_list, child_node)
-		clk_disable_unused_subtree(clk);
+	hlist_for_each_entry(core, &clk_orphan_list, child_node)
+		clk_disable_unused_subtree(core);
 
-	hlist_for_each_entry(clk, &clk_root_list, child_node)
-		clk_unprepare_unused_subtree(clk);
+	hlist_for_each_entry(core, &clk_root_list, child_node)
+		clk_unprepare_unused_subtree(core);
 
-	hlist_for_each_entry(clk, &clk_orphan_list, child_node)
-		clk_unprepare_unused_subtree(clk);
+	hlist_for_each_entry(core, &clk_orphan_list, child_node)
+		clk_unprepare_unused_subtree(core);
 
 	clk_prepare_unlock();
 
@@ -608,18 +608,18 @@ struct clk *__clk_get_parent(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(__clk_get_parent);
 
-static struct clk_core *clk_core_get_parent_by_index(struct clk_core *clk,
+static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core,
 							 u8 index)
 {
-	if (!clk || index >= clk->num_parents)
+	if (!core || index >= core->num_parents)
 		return NULL;
-	else if (!clk->parents)
-		return clk_core_lookup(clk->parent_names[index]);
-	else if (!clk->parents[index])
-		return clk->parents[index] =
-			clk_core_lookup(clk->parent_names[index]);
+	else if (!core->parents)
+		return clk_core_lookup(core->parent_names[index]);
+	else if (!core->parents[index])
+		return core->parents[index] =
+			clk_core_lookup(core->parent_names[index]);
 	else
-		return clk->parents[index];
+		return core->parents[index];
 }
 
 struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
@@ -640,21 +640,21 @@ unsigned int __clk_get_enable_count(struct clk *clk)
 	return !clk ? 0 : clk->core->enable_count;
 }
 
-static unsigned long clk_core_get_rate_nolock(struct clk_core *clk)
+static unsigned long clk_core_get_rate_nolock(struct clk_core *core)
 {
 	unsigned long ret;
 
-	if (!clk) {
+	if (!core) {
 		ret = 0;
 		goto out;
 	}
 
-	ret = clk->rate;
+	ret = core->rate;
 
-	if (clk->flags & CLK_IS_ROOT)
+	if (core->flags & CLK_IS_ROOT)
 		goto out;
 
-	if (!clk->parent)
+	if (!core->parent)
 		ret = 0;
 
 out:
@@ -670,12 +670,12 @@ unsigned long __clk_get_rate(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(__clk_get_rate);
 
-static unsigned long __clk_get_accuracy(struct clk_core *clk)
+static unsigned long __clk_get_accuracy(struct clk_core *core)
 {
-	if (!clk)
+	if (!core)
 		return 0;
 
-	return clk->accuracy;
+	return core->accuracy;
 }
 
 unsigned long __clk_get_flags(struct clk *clk)
@@ -684,23 +684,23 @@ unsigned long __clk_get_flags(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(__clk_get_flags);
 
-static bool clk_core_is_prepared(struct clk_core *clk)
+static bool clk_core_is_prepared(struct clk_core *core)
 {
 	int ret;
 
-	if (!clk)
+	if (!core)
 		return false;
 
 	/*
 	 * .is_prepared is optional for clocks that can prepare
 	 * fall back to software usage counter if it is missing
 	 */
-	if (!clk->ops->is_prepared) {
-		ret = clk->prepare_count ? 1 : 0;
+	if (!core->ops->is_prepared) {
+		ret = core->prepare_count ? 1 : 0;
 		goto out;
 	}
 
-	ret = clk->ops->is_prepared(clk->hw);
+	ret = core->ops->is_prepared(core->hw);
 out:
 	return !!ret;
 }
@@ -713,23 +713,23 @@ bool __clk_is_prepared(struct clk *clk)
 	return clk_core_is_prepared(clk->core);
 }
 
-static bool clk_core_is_enabled(struct clk_core *clk)
+static bool clk_core_is_enabled(struct clk_core *core)
 {
 	int ret;
 
-	if (!clk)
+	if (!core)
 		return false;
 
 	/*
 	 * .is_enabled is only mandatory for clocks that gate
 	 * fall back to software usage counter if .is_enabled is missing
 	 */
-	if (!clk->ops->is_enabled) {
-		ret = clk->enable_count ? 1 : 0;
+	if (!core->ops->is_enabled) {
+		ret = core->enable_count ? 1 : 0;
 		goto out;
 	}
 
-	ret = clk->ops->is_enabled(clk->hw);
+	ret = core->ops->is_enabled(core->hw);
 out:
 	return !!ret;
 }
@@ -744,15 +744,15 @@ bool __clk_is_enabled(struct clk *clk)
 EXPORT_SYMBOL_GPL(__clk_is_enabled);
 
 static struct clk_core *__clk_lookup_subtree(const char *name,
-					     struct clk_core *clk)
+					     struct clk_core *core)
 {
 	struct clk_core *child;
 	struct clk_core *ret;
 
-	if (!strcmp(clk->name, name))
-		return clk;
+	if (!strcmp(core->name, name))
+		return core;
 
-	hlist_for_each_entry(child, &clk->children, child_node) {
+	hlist_for_each_entry(child, &core->children, child_node) {
 		ret = __clk_lookup_subtree(name, child);
 		if (ret)
 			return ret;
@@ -853,7 +853,7 @@ struct clk *__clk_lookup(const char *name)
 	return !core ? NULL : core->hw->clk;
 }
 
-static void clk_core_get_boundaries(struct clk_core *clk,
+static void clk_core_get_boundaries(struct clk_core *core,
 				    unsigned long *min_rate,
 				    unsigned long *max_rate)
 {
@@ -862,10 +862,10 @@ static void clk_core_get_boundaries(struct clk_core *clk,
 	*min_rate = 0;
 	*max_rate = ULONG_MAX;
 
-	hlist_for_each_entry(clk_user, &clk->clks, clks_node)
+	hlist_for_each_entry(clk_user, &core->clks, clks_node)
 		*min_rate = max(*min_rate, clk_user->min_rate);
 
-	hlist_for_each_entry(clk_user, &clk->clks, clks_node)
+	hlist_for_each_entry(clk_user, &core->clks, clks_node)
 		*max_rate = min(*max_rate, clk_user->max_rate);
 }
 
@@ -901,26 +901,26 @@ EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest);
 
 /***        clk api        ***/
 
-static void clk_core_unprepare(struct clk_core *clk)
+static void clk_core_unprepare(struct clk_core *core)
 {
-	if (!clk)
+	if (!core)
 		return;
 
-	if (WARN_ON(clk->prepare_count == 0))
+	if (WARN_ON(core->prepare_count == 0))
 		return;
 
-	if (--clk->prepare_count > 0)
+	if (--core->prepare_count > 0)
 		return;
 
-	WARN_ON(clk->enable_count > 0);
+	WARN_ON(core->enable_count > 0);
 
-	trace_clk_unprepare(clk);
+	trace_clk_unprepare(core);
 
-	if (clk->ops->unprepare)
-		clk->ops->unprepare(clk->hw);
+	if (core->ops->unprepare)
+		core->ops->unprepare(core->hw);
 
-	trace_clk_unprepare_complete(clk);
-	clk_core_unprepare(clk->parent);
+	trace_clk_unprepare_complete(core);
+	clk_core_unprepare(core->parent);
 }
 
 /**
@@ -945,32 +945,32 @@ void clk_unprepare(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_unprepare);
 
-static int clk_core_prepare(struct clk_core *clk)
+static int clk_core_prepare(struct clk_core *core)
 {
 	int ret = 0;
 
-	if (!clk)
+	if (!core)
 		return 0;
 
-	if (clk->prepare_count == 0) {
-		ret = clk_core_prepare(clk->parent);
+	if (core->prepare_count == 0) {
+		ret = clk_core_prepare(core->parent);
 		if (ret)
 			return ret;
 
-		trace_clk_prepare(clk);
+		trace_clk_prepare(core);
 
-		if (clk->ops->prepare)
-			ret = clk->ops->prepare(clk->hw);
+		if (core->ops->prepare)
+			ret = core->ops->prepare(core->hw);
 
-		trace_clk_prepare_complete(clk);
+		trace_clk_prepare_complete(core);
 
 		if (ret) {
-			clk_core_unprepare(clk->parent);
+			clk_core_unprepare(core->parent);
 			return ret;
 		}
 	}
 
-	clk->prepare_count++;
+	core->prepare_count++;
 
 	return 0;
 }
@@ -1002,25 +1002,25 @@ int clk_prepare(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_prepare);
 
-static void clk_core_disable(struct clk_core *clk)
+static void clk_core_disable(struct clk_core *core)
 {
-	if (!clk)
+	if (!core)
 		return;
 
-	if (WARN_ON(clk->enable_count == 0))
+	if (WARN_ON(core->enable_count == 0))
 		return;
 
-	if (--clk->enable_count > 0)
+	if (--core->enable_count > 0)
 		return;
 
-	trace_clk_disable(clk);
+	trace_clk_disable(core);
 
-	if (clk->ops->disable)
-		clk->ops->disable(clk->hw);
+	if (core->ops->disable)
+		core->ops->disable(core->hw);
 
-	trace_clk_disable_complete(clk);
+	trace_clk_disable_complete(core);
 
-	clk_core_disable(clk->parent);
+	clk_core_disable(core->parent);
 }
 
 static void __clk_disable(struct clk *clk)
@@ -1056,36 +1056,36 @@ void clk_disable(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
-static int clk_core_enable(struct clk_core *clk)
+static int clk_core_enable(struct clk_core *core)
 {
 	int ret = 0;
 
-	if (!clk)
+	if (!core)
 		return 0;
 
-	if (WARN_ON(clk->prepare_count == 0))
+	if (WARN_ON(core->prepare_count == 0))
 		return -ESHUTDOWN;
 
-	if (clk->enable_count == 0) {
-		ret = clk_core_enable(clk->parent);
+	if (core->enable_count == 0) {
+		ret = clk_core_enable(core->parent);
 
 		if (ret)
 			return ret;
 
-		trace_clk_enable(clk);
+		trace_clk_enable(core);
 
-		if (clk->ops->enable)
-			ret = clk->ops->enable(clk->hw);
+		if (core->ops->enable)
+			ret = core->ops->enable(core->hw);
 
-		trace_clk_enable_complete(clk);
+		trace_clk_enable_complete(core);
 
 		if (ret) {
-			clk_core_disable(clk->parent);
+			clk_core_disable(core->parent);
 			return ret;
 		}
 	}
 
-	clk->enable_count++;
+	core->enable_count++;
 	return 0;
 }
 
@@ -1123,7 +1123,7 @@ int clk_enable(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_enable);
 
-static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
+static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
 						unsigned long rate,
 						unsigned long min_rate,
 						unsigned long max_rate)
@@ -1134,25 +1134,25 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
 
 	lockdep_assert_held(&prepare_lock);
 
-	if (!clk)
+	if (!core)
 		return 0;
 
-	parent = clk->parent;
+	parent = core->parent;
 	if (parent)
 		parent_rate = parent->rate;
 
-	if (clk->ops->determine_rate) {
+	if (core->ops->determine_rate) {
 		parent_hw = parent ? parent->hw : NULL;
-		return clk->ops->determine_rate(clk->hw, rate,
+		return core->ops->determine_rate(core->hw, rate,
 						min_rate, max_rate,
 						&parent_rate, &parent_hw);
-	} else if (clk->ops->round_rate)
-		return clk->ops->round_rate(clk->hw, rate, &parent_rate);
-	else if (clk->flags & CLK_SET_RATE_PARENT)
-		return clk_core_round_rate_nolock(clk->parent, rate, min_rate,
+	} else if (core->ops->round_rate)
+		return core->ops->round_rate(core->hw, rate, &parent_rate);
+	else if (core->flags & CLK_SET_RATE_PARENT)
+		return clk_core_round_rate_nolock(core->parent, rate, min_rate,
 						  max_rate);
 	else
-		return clk->rate;
+		return core->rate;
 }
 
 /**
@@ -1224,7 +1224,7 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
 
 /**
  * __clk_notify - call clk notifier chain
- * @clk: struct clk * that is changing rate
+ * @core: clk that is changing rate
  * @msg: clk notifier type (see include/linux/clk.h)
  * @old_rate: old clk rate
  * @new_rate: new clk rate
@@ -1236,7 +1236,7 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
  * called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
  * a driver returns that.
  */
-static int __clk_notify(struct clk_core *clk, unsigned long msg,
+static int __clk_notify(struct clk_core *core, unsigned long msg,
 		unsigned long old_rate, unsigned long new_rate)
 {
 	struct clk_notifier *cn;
@@ -1247,7 +1247,7 @@ static int __clk_notify(struct clk_core *clk, unsigned long msg,
 	cnd.new_rate = new_rate;
 
 	list_for_each_entry(cn, &clk_notifier_list, node) {
-		if (cn->clk->core == clk) {
+		if (cn->clk->core == core) {
 			cnd.clk = cn->clk;
 			ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
 					&cnd);
@@ -1259,7 +1259,7 @@ static int __clk_notify(struct clk_core *clk, unsigned long msg,
 
 /**
  * __clk_recalc_accuracies
- * @clk: first clk in the subtree
+ * @core: first clk in the subtree
  *
  * Walks the subtree of clks starting with clk and recalculates accuracies as
  * it goes.  Note that if a clk does not implement the .recalc_accuracy
@@ -1268,35 +1268,35 @@ static int __clk_notify(struct clk_core *clk, unsigned long msg,
  *
  * Caller must hold prepare_lock.
  */
-static void __clk_recalc_accuracies(struct clk_core *clk)
+static void __clk_recalc_accuracies(struct clk_core *core)
 {
 	unsigned long parent_accuracy = 0;
 	struct clk_core *child;
 
 	lockdep_assert_held(&prepare_lock);
 
-	if (clk->parent)
-		parent_accuracy = clk->parent->accuracy;
+	if (core->parent)
+		parent_accuracy = core->parent->accuracy;
 
-	if (clk->ops->recalc_accuracy)
-		clk->accuracy = clk->ops->recalc_accuracy(clk->hw,
+	if (core->ops->recalc_accuracy)
+		core->accuracy = core->ops->recalc_accuracy(core->hw,
 							  parent_accuracy);
 	else
-		clk->accuracy = parent_accuracy;
+		core->accuracy = parent_accuracy;
 
-	hlist_for_each_entry(child, &clk->children, child_node)
+	hlist_for_each_entry(child, &core->children, child_node)
 		__clk_recalc_accuracies(child);
 }
 
-static long clk_core_get_accuracy(struct clk_core *clk)
+static long clk_core_get_accuracy(struct clk_core *core)
 {
 	unsigned long accuracy;
 
 	clk_prepare_lock();
-	if (clk && (clk->flags & CLK_GET_ACCURACY_NOCACHE))
-		__clk_recalc_accuracies(clk);
+	if (core && (core->flags & CLK_GET_ACCURACY_NOCACHE))
+		__clk_recalc_accuracies(core);
 
-	accuracy = __clk_get_accuracy(clk);
+	accuracy = __clk_get_accuracy(core);
 	clk_prepare_unlock();
 
 	return accuracy;
@@ -1320,17 +1320,17 @@ long clk_get_accuracy(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_get_accuracy);
 
-static unsigned long clk_recalc(struct clk_core *clk,
+static unsigned long clk_recalc(struct clk_core *core,
 				unsigned long parent_rate)
 {
-	if (clk->ops->recalc_rate)
-		return clk->ops->recalc_rate(clk->hw, parent_rate);
+	if (core->ops->recalc_rate)
+		return core->ops->recalc_rate(core->hw, parent_rate);
 	return parent_rate;
 }
 
 /**
  * __clk_recalc_rates
- * @clk: first clk in the subtree
+ * @core: first clk in the subtree
  * @msg: notification type (see include/linux/clk.h)
  *
  * Walks the subtree of clks starting with clk and recalculates rates as it
@@ -1342,7 +1342,7 @@ static unsigned long clk_recalc(struct clk_core *clk,
  *
  * Caller must hold prepare_lock.
  */
-static void __clk_recalc_rates(struct clk_core *clk, unsigned long msg)
+static void __clk_recalc_rates(struct clk_core *core, unsigned long msg)
 {
 	unsigned long old_rate;
 	unsigned long parent_rate = 0;
@@ -1350,34 +1350,34 @@ static void __clk_recalc_rates(struct clk_core *clk, unsigned long msg)
 
 	lockdep_assert_held(&prepare_lock);
 
-	old_rate = clk->rate;
+	old_rate = core->rate;
 
-	if (clk->parent)
-		parent_rate = clk->parent->rate;
+	if (core->parent)
+		parent_rate = core->parent->rate;
 
-	clk->rate = clk_recalc(clk, parent_rate);
+	core->rate = clk_recalc(core, parent_rate);
 
 	/*
 	 * ignore NOTIFY_STOP and NOTIFY_BAD return values for POST_RATE_CHANGE
 	 * & ABORT_RATE_CHANGE notifiers
 	 */
-	if (clk->notifier_count && msg)
-		__clk_notify(clk, msg, old_rate, clk->rate);
+	if (core->notifier_count && msg)
+		__clk_notify(core, msg, old_rate, core->rate);
 
-	hlist_for_each_entry(child, &clk->children, child_node)
+	hlist_for_each_entry(child, &core->children, child_node)
 		__clk_recalc_rates(child, msg);
 }
 
-static unsigned long clk_core_get_rate(struct clk_core *clk)
+static unsigned long clk_core_get_rate(struct clk_core *core)
 {
 	unsigned long rate;
 
 	clk_prepare_lock();
 
-	if (clk && (clk->flags & CLK_GET_RATE_NOCACHE))
-		__clk_recalc_rates(clk, 0);
+	if (core && (core->flags & CLK_GET_RATE_NOCACHE))
+		__clk_recalc_rates(core, 0);
 
-	rate = clk_core_get_rate_nolock(clk);
+	rate = clk_core_get_rate_nolock(core);
 	clk_prepare_unlock();
 
 	return rate;
@@ -1400,15 +1400,15 @@ unsigned long clk_get_rate(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_get_rate);
 
-static int clk_fetch_parent_index(struct clk_core *clk,
+static int clk_fetch_parent_index(struct clk_core *core,
 				  struct clk_core *parent)
 {
 	int i;
 
-	if (!clk->parents) {
-		clk->parents = kcalloc(clk->num_parents,
+	if (!core->parents) {
+		core->parents = kcalloc(core->num_parents,
 					sizeof(struct clk *), GFP_KERNEL);
-		if (!clk->parents)
+		if (!core->parents)
 			return -ENOMEM;
 	}
 
@@ -1417,15 +1417,15 @@ static int clk_fetch_parent_index(struct clk_core *clk,
 	 * or if not yet cached, use string name comparison and cache
 	 * them now to avoid future calls to clk_core_lookup.
 	 */
-	for (i = 0; i < clk->num_parents; i++) {
-		if (clk->parents[i] == parent)
+	for (i = 0; i < core->num_parents; i++) {
+		if (core->parents[i] == parent)
 			return i;
 
-		if (clk->parents[i])
+		if (core->parents[i])
 			continue;
 
-		if (!strcmp(clk->parent_names[i], parent->name)) {
-			clk->parents[i] = clk_core_lookup(parent->name);
+		if (!strcmp(core->parent_names[i], parent->name)) {
+			core->parents[i] = clk_core_lookup(parent->name);
 			return i;
 		}
 	}
@@ -1433,28 +1433,28 @@ static int clk_fetch_parent_index(struct clk_core *clk,
 	return -EINVAL;
 }
 
-static void clk_reparent(struct clk_core *clk, struct clk_core *new_parent)
+static void clk_reparent(struct clk_core *core, struct clk_core *new_parent)
 {
-	hlist_del(&clk->child_node);
+	hlist_del(&core->child_node);
 
 	if (new_parent) {
 		/* avoid duplicate POST_RATE_CHANGE notifications */
-		if (new_parent->new_child == clk)
+		if (new_parent->new_child == core)
 			new_parent->new_child = NULL;
 
-		hlist_add_head(&clk->child_node, &new_parent->children);
+		hlist_add_head(&core->child_node, &new_parent->children);
 	} else {
-		hlist_add_head(&clk->child_node, &clk_orphan_list);
+		hlist_add_head(&core->child_node, &clk_orphan_list);
 	}
 
-	clk->parent = new_parent;
+	core->parent = new_parent;
 }
 
-static struct clk_core *__clk_set_parent_before(struct clk_core *clk,
+static struct clk_core *__clk_set_parent_before(struct clk_core *core,
 					   struct clk_core *parent)
 {
 	unsigned long flags;
-	struct clk_core *old_parent = clk->parent;
+	struct clk_core *old_parent = core->parent;
 
 	/*
 	 * Migrate prepare state between parents and prevent race with
@@ -1473,15 +1473,15 @@ static struct clk_core *__clk_set_parent_before(struct clk_core *clk,
 	 *
 	 * See also: Comment for clk_set_parent() below.
 	 */
-	if (clk->prepare_count) {
+	if (core->prepare_count) {
 		clk_core_prepare(parent);
 		clk_core_enable(parent);
-		clk_core_enable(clk);
+		clk_core_enable(core);
 	}
 
 	/* update the clk tree topology */
 	flags = clk_enable_lock();
-	clk_reparent(clk, parent);
+	clk_reparent(core, parent);
 	clk_enable_unlock(flags);
 
 	return old_parent;
@@ -1502,44 +1502,44 @@ static void __clk_set_parent_after(struct clk_core *core,
 	}
 }
 
-static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent,
+static int __clk_set_parent(struct clk_core *core, struct clk_core *parent,
 			    u8 p_index)
 {
 	unsigned long flags;
 	int ret = 0;
 	struct clk_core *old_parent;
 
-	old_parent = __clk_set_parent_before(clk, parent);
+	old_parent = __clk_set_parent_before(core, parent);
 
-	trace_clk_set_parent(clk, parent);
+	trace_clk_set_parent(core, parent);
 
 	/* change clock input source */
-	if (parent && clk->ops->set_parent)
-		ret = clk->ops->set_parent(clk->hw, p_index);
+	if (parent && core->ops->set_parent)
+		ret = core->ops->set_parent(core->hw, p_index);
 
-	trace_clk_set_parent_complete(clk, parent);
+	trace_clk_set_parent_complete(core, parent);
 
 	if (ret) {
 		flags = clk_enable_lock();
-		clk_reparent(clk, old_parent);
+		clk_reparent(core, old_parent);
 		clk_enable_unlock(flags);
 
-		if (clk->prepare_count) {
-			clk_core_disable(clk);
+		if (core->prepare_count) {
+			clk_core_disable(core);
 			clk_core_disable(parent);
 			clk_core_unprepare(parent);
 		}
 		return ret;
 	}
 
-	__clk_set_parent_after(clk, parent, old_parent);
+	__clk_set_parent_after(core, parent, old_parent);
 
 	return 0;
 }
 
 /**
  * __clk_speculate_rates
- * @clk: first clk in the subtree
+ * @core: first clk in the subtree
  * @parent_rate: the "future" rate of clk's parent
  *
  * Walks the subtree of clks starting with clk, speculating rates as it
@@ -1553,7 +1553,7 @@ static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent,
  *
  * Caller must hold prepare_lock.
  */
-static int __clk_speculate_rates(struct clk_core *clk,
+static int __clk_speculate_rates(struct clk_core *core,
 				 unsigned long parent_rate)
 {
 	struct clk_core *child;
@@ -1562,19 +1562,19 @@ static int __clk_speculate_rates(struct clk_core *clk,
 
 	lockdep_assert_held(&prepare_lock);
 
-	new_rate = clk_recalc(clk, parent_rate);
+	new_rate = clk_recalc(core, parent_rate);
 
 	/* abort rate change if a driver returns NOTIFY_BAD or NOTIFY_STOP */
-	if (clk->notifier_count)
-		ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate);
+	if (core->notifier_count)
+		ret = __clk_notify(core, PRE_RATE_CHANGE, core->rate, new_rate);
 
 	if (ret & NOTIFY_STOP_MASK) {
 		pr_debug("%s: clk notifier callback for clock %s aborted with error %d\n",
-				__func__, clk->name, ret);
+				__func__, core->name, ret);
 		goto out;
 	}
 
-	hlist_for_each_entry(child, &clk->children, child_node) {
+	hlist_for_each_entry(child, &core->children, child_node) {
 		ret = __clk_speculate_rates(child, new_rate);
 		if (ret & NOTIFY_STOP_MASK)
 			break;
@@ -1584,20 +1584,20 @@ out:
 	return ret;
 }
 
-static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate,
+static void clk_calc_subtree(struct clk_core *core, unsigned long new_rate,
 			     struct clk_core *new_parent, u8 p_index)
 {
 	struct clk_core *child;
 
-	clk->new_rate = new_rate;
-	clk->new_parent = new_parent;
-	clk->new_parent_index = p_index;
+	core->new_rate = new_rate;
+	core->new_parent = new_parent;
+	core->new_parent_index = p_index;
 	/* include clk in new parent's PRE_RATE_CHANGE notifications */
-	clk->new_child = NULL;
-	if (new_parent && new_parent != clk->parent)
-		new_parent->new_child = clk;
+	core->new_child = NULL;
+	if (new_parent && new_parent != core->parent)
+		new_parent->new_child = core;
 
-	hlist_for_each_entry(child, &clk->children, child_node) {
+	hlist_for_each_entry(child, &core->children, child_node) {
 		child->new_rate = clk_recalc(child, new_rate);
 		clk_calc_subtree(child, child->new_rate, NULL, 0);
 	}
@@ -1607,10 +1607,10 @@ static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate,
  * calculate the new rates returning the topmost clock that has to be
  * changed.
  */
-static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
+static struct clk_core *clk_calc_new_rates(struct clk_core *core,
 					   unsigned long rate)
 {
-	struct clk_core *top = clk;
+	struct clk_core *top = core;
 	struct clk_core *old_parent, *parent;
 	struct clk_hw *parent_hw;
 	unsigned long best_parent_rate = 0;
@@ -1621,20 +1621,20 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
 	long ret;
 
 	/* sanity */
-	if (IS_ERR_OR_NULL(clk))
+	if (IS_ERR_OR_NULL(core))
 		return NULL;
 
 	/* save parent rate, if it exists */
-	parent = old_parent = clk->parent;
+	parent = old_parent = core->parent;
 	if (parent)
 		best_parent_rate = parent->rate;
 
-	clk_core_get_boundaries(clk, &min_rate, &max_rate);
+	clk_core_get_boundaries(core, &min_rate, &max_rate);
 
 	/* find the closest rate and parent clk/rate */
-	if (clk->ops->determine_rate) {
+	if (core->ops->determine_rate) {
 		parent_hw = parent ? parent->hw : NULL;
-		ret = clk->ops->determine_rate(clk->hw, rate,
+		ret = core->ops->determine_rate(core->hw, rate,
 					       min_rate,
 					       max_rate,
 					       &best_parent_rate,
@@ -1644,8 +1644,8 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
 
 		new_rate = ret;
 		parent = parent_hw ? parent_hw->core : NULL;
-	} else if (clk->ops->round_rate) {
-		ret = clk->ops->round_rate(clk->hw, rate,
+	} else if (core->ops->round_rate) {
+		ret = core->ops->round_rate(core->hw, rate,
 					   &best_parent_rate);
 		if (ret < 0)
 			return NULL;
@@ -1653,9 +1653,9 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
 		new_rate = ret;
 		if (new_rate < min_rate || new_rate > max_rate)
 			return NULL;
-	} else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) {
+	} else if (!parent || !(core->flags & CLK_SET_RATE_PARENT)) {
 		/* pass-through clock without adjustable parent */
-		clk->new_rate = clk->rate;
+		core->new_rate = core->rate;
 		return NULL;
 	} else {
 		/* pass-through clock with adjustable parent */
@@ -1666,28 +1666,28 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
 
 	/* some clocks must be gated to change parent */
 	if (parent != old_parent &&
-	    (clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) {
+	    (core->flags & CLK_SET_PARENT_GATE) && core->prepare_count) {
 		pr_debug("%s: %s not gated but wants to reparent\n",
-			 __func__, clk->name);
+			 __func__, core->name);
 		return NULL;
 	}
 
 	/* try finding the new parent index */
-	if (parent && clk->num_parents > 1) {
-		p_index = clk_fetch_parent_index(clk, parent);
+	if (parent && core->num_parents > 1) {
+		p_index = clk_fetch_parent_index(core, parent);
 		if (p_index < 0) {
 			pr_debug("%s: clk %s can not be parent of clk %s\n",
-				 __func__, parent->name, clk->name);
+				 __func__, parent->name, core->name);
 			return NULL;
 		}
 	}
 
-	if ((clk->flags & CLK_SET_RATE_PARENT) && parent &&
+	if ((core->flags & CLK_SET_RATE_PARENT) && parent &&
 	    best_parent_rate != parent->rate)
 		top = clk_calc_new_rates(parent, best_parent_rate);
 
 out:
-	clk_calc_subtree(clk, new_rate, parent, p_index);
+	clk_calc_subtree(core, new_rate, parent, p_index);
 
 	return top;
 }
@@ -1697,33 +1697,33 @@ out:
  * so that in case of an error we can walk down the whole tree again and
  * abort the change.
  */
-static struct clk_core *clk_propagate_rate_change(struct clk_core *clk,
+static struct clk_core *clk_propagate_rate_change(struct clk_core *core,
 						  unsigned long event)
 {
 	struct clk_core *child, *tmp_clk, *fail_clk = NULL;
 	int ret = NOTIFY_DONE;
 
-	if (clk->rate == clk->new_rate)
+	if (core->rate == core->new_rate)
 		return NULL;
 
-	if (clk->notifier_count) {
-		ret = __clk_notify(clk, event, clk->rate, clk->new_rate);
+	if (core->notifier_count) {
+		ret = __clk_notify(core, event, core->rate, core->new_rate);
 		if (ret & NOTIFY_STOP_MASK)
-			fail_clk = clk;
+			fail_clk = core;
 	}
 
-	hlist_for_each_entry(child, &clk->children, child_node) {
+	hlist_for_each_entry(child, &core->children, child_node) {
 		/* Skip children who will be reparented to another clock */
-		if (child->new_parent && child->new_parent != clk)
+		if (child->new_parent && child->new_parent != core)
 			continue;
 		tmp_clk = clk_propagate_rate_change(child, event);
 		if (tmp_clk)
 			fail_clk = tmp_clk;
 	}
 
-	/* handle the new child who might not be in clk->children yet */
-	if (clk->new_child) {
-		tmp_clk = clk_propagate_rate_change(clk->new_child, event);
+	/* handle the new child who might not be in core->children yet */
+	if (core->new_child) {
+		tmp_clk = clk_propagate_rate_change(core->new_child, event);
 		if (tmp_clk)
 			fail_clk = tmp_clk;
 	}
@@ -1735,7 +1735,7 @@ static struct clk_core *clk_propagate_rate_change(struct clk_core *clk,
  * walk down a subtree and set the new rates notifying the rate
  * change on the way
  */
-static void clk_change_rate(struct clk_core *clk)
+static void clk_change_rate(struct clk_core *core)
 {
 	struct clk_core *child;
 	struct hlist_node *tmp;
@@ -1744,77 +1744,77 @@ static void clk_change_rate(struct clk_core *clk)
 	bool skip_set_rate = false;
 	struct clk_core *old_parent;
 
-	old_rate = clk->rate;
+	old_rate = core->rate;
 
-	if (clk->new_parent)
-		best_parent_rate = clk->new_parent->rate;
-	else if (clk->parent)
-		best_parent_rate = clk->parent->rate;
+	if (core->new_parent)
+		best_parent_rate = core->new_parent->rate;
+	else if (core->parent)
+		best_parent_rate = core->parent->rate;
 
-	if (clk->new_parent && clk->new_parent != clk->parent) {
-		old_parent = __clk_set_parent_before(clk, clk->new_parent);
-		trace_clk_set_parent(clk, clk->new_parent);
+	if (core->new_parent && core->new_parent != core->parent) {
+		old_parent = __clk_set_parent_before(core, core->new_parent);
+		trace_clk_set_parent(core, core->new_parent);
 
-		if (clk->ops->set_rate_and_parent) {
+		if (core->ops->set_rate_and_parent) {
 			skip_set_rate = true;
-			clk->ops->set_rate_and_parent(clk->hw, clk->new_rate,
+			core->ops->set_rate_and_parent(core->hw, core->new_rate,
 					best_parent_rate,
-					clk->new_parent_index);
-		} else if (clk->ops->set_parent) {
-			clk->ops->set_parent(clk->hw, clk->new_parent_index);
+					core->new_parent_index);
+		} else if (core->ops->set_parent) {
+			core->ops->set_parent(core->hw, core->new_parent_index);
 		}
 
-		trace_clk_set_parent_complete(clk, clk->new_parent);
-		__clk_set_parent_after(clk, clk->new_parent, old_parent);
+		trace_clk_set_parent_complete(core, core->new_parent);
+		__clk_set_parent_after(core, core->new_parent, old_parent);
 	}
 
-	trace_clk_set_rate(clk, clk->new_rate);
+	trace_clk_set_rate(core, core->new_rate);
 
-	if (!skip_set_rate && clk->ops->set_rate)
-		clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate);
+	if (!skip_set_rate && core->ops->set_rate)
+		core->ops->set_rate(core->hw, core->new_rate, best_parent_rate);
 
-	trace_clk_set_rate_complete(clk, clk->new_rate);
+	trace_clk_set_rate_complete(core, core->new_rate);
 
-	clk->rate = clk_recalc(clk, best_parent_rate);
+	core->rate = clk_recalc(core, best_parent_rate);
 
-	if (clk->notifier_count && old_rate != clk->rate)
-		__clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
+	if (core->notifier_count && old_rate != core->rate)
+		__clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate);
 
 	/*
 	 * Use safe iteration, as change_rate can actually swap parents
 	 * for certain clock types.
 	 */
-	hlist_for_each_entry_safe(child, tmp, &clk->children, child_node) {
+	hlist_for_each_entry_safe(child, tmp, &core->children, child_node) {
 		/* Skip children who will be reparented to another clock */
-		if (child->new_parent && child->new_parent != clk)
+		if (child->new_parent && child->new_parent != core)
 			continue;
 		clk_change_rate(child);
 	}
 
-	/* handle the new child who might not be in clk->children yet */
-	if (clk->new_child)
-		clk_change_rate(clk->new_child);
+	/* handle the new child who might not be in core->children yet */
+	if (core->new_child)
+		clk_change_rate(core->new_child);
 }
 
-static int clk_core_set_rate_nolock(struct clk_core *clk,
+static int clk_core_set_rate_nolock(struct clk_core *core,
 				    unsigned long req_rate)
 {
 	struct clk_core *top, *fail_clk;
 	unsigned long rate = req_rate;
 	int ret = 0;
 
-	if (!clk)
+	if (!core)
 		return 0;
 
 	/* bail early if nothing to do */
-	if (rate == clk_core_get_rate_nolock(clk))
+	if (rate == clk_core_get_rate_nolock(core))
 		return 0;
 
-	if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count)
+	if ((core->flags & CLK_SET_RATE_GATE) && core->prepare_count)
 		return -EBUSY;
 
 	/* calculate new rates and get the topmost changed clock */
-	top = clk_calc_new_rates(clk, rate);
+	top = clk_calc_new_rates(core, rate);
 	if (!top)
 		return -EINVAL;
 
@@ -1830,7 +1830,7 @@ static int clk_core_set_rate_nolock(struct clk_core *clk,
 	/* change the rates */
 	clk_change_rate(top);
 
-	clk->req_rate = req_rate;
+	core->req_rate = req_rate;
 
 	return ret;
 }
@@ -1969,55 +1969,55 @@ EXPORT_SYMBOL_GPL(clk_get_parent);
  * .parents array exists, and if so use it to avoid an expensive tree
  * traversal.  If .parents does not exist then walk the tree.
  */
-static struct clk_core *__clk_init_parent(struct clk_core *clk)
+static struct clk_core *__clk_init_parent(struct clk_core *core)
 {
 	struct clk_core *ret = NULL;
 	u8 index;
 
 	/* handle the trivial cases */
 
-	if (!clk->num_parents)
+	if (!core->num_parents)
 		goto out;
 
-	if (clk->num_parents == 1) {
-		if (IS_ERR_OR_NULL(clk->parent))
-			clk->parent = clk_core_lookup(clk->parent_names[0]);
-		ret = clk->parent;
+	if (core->num_parents == 1) {
+		if (IS_ERR_OR_NULL(core->parent))
+			core->parent = clk_core_lookup(core->parent_names[0]);
+		ret = core->parent;
 		goto out;
 	}
 
-	if (!clk->ops->get_parent) {
-		WARN(!clk->ops->get_parent,
+	if (!core->ops->get_parent) {
+		WARN(!core->ops->get_parent,
 			"%s: multi-parent clocks must implement .get_parent\n",
 			__func__);
 		goto out;
 	};
 
 	/*
-	 * Do our best to cache parent clocks in clk->parents.  This prevents
-	 * unnecessary and expensive lookups.  We don't set clk->parent here;
+	 * Do our best to cache parent clocks in core->parents.  This prevents
+	 * unnecessary and expensive lookups.  We don't set core->parent here;
 	 * that is done by the calling function.
 	 */
 
-	index = clk->ops->get_parent(clk->hw);
+	index = core->ops->get_parent(core->hw);
 
-	if (!clk->parents)
-		clk->parents =
-			kcalloc(clk->num_parents, sizeof(struct clk *),
+	if (!core->parents)
+		core->parents =
+			kcalloc(core->num_parents, sizeof(struct clk *),
 					GFP_KERNEL);
 
-	ret = clk_core_get_parent_by_index(clk, index);
+	ret = clk_core_get_parent_by_index(core, index);
 
 out:
 	return ret;
 }
 
-static void clk_core_reparent(struct clk_core *clk,
+static void clk_core_reparent(struct clk_core *core,
 				  struct clk_core *new_parent)
 {
-	clk_reparent(clk, new_parent);
-	__clk_recalc_accuracies(clk);
-	__clk_recalc_rates(clk, POST_RATE_CHANGE);
+	clk_reparent(core, new_parent);
+	__clk_recalc_accuracies(core);
+	__clk_recalc_rates(core, POST_RATE_CHANGE);
 }
 
 /**
@@ -2054,61 +2054,61 @@ bool clk_has_parent(struct clk *clk, struct clk *parent)
 }
 EXPORT_SYMBOL_GPL(clk_has_parent);
 
-static int clk_core_set_parent(struct clk_core *clk, struct clk_core *parent)
+static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
 {
 	int ret = 0;
 	int p_index = 0;
 	unsigned long p_rate = 0;
 
-	if (!clk)
+	if (!core)
 		return 0;
 
 	/* prevent racing with updates to the clock topology */
 	clk_prepare_lock();
 
-	if (clk->parent == parent)
+	if (core->parent == parent)
 		goto out;
 
 	/* verify ops for for multi-parent clks */
-	if ((clk->num_parents > 1) && (!clk->ops->set_parent)) {
+	if ((core->num_parents > 1) && (!core->ops->set_parent)) {
 		ret = -ENOSYS;
 		goto out;
 	}
 
 	/* check that we are allowed to re-parent if the clock is in use */
-	if ((clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) {
+	if ((core->flags & CLK_SET_PARENT_GATE) && core->prepare_count) {
 		ret = -EBUSY;
 		goto out;
 	}
 
 	/* try finding the new parent index */
 	if (parent) {
-		p_index = clk_fetch_parent_index(clk, parent);
+		p_index = clk_fetch_parent_index(core, parent);
 		p_rate = parent->rate;
 		if (p_index < 0) {
 			pr_debug("%s: clk %s can not be parent of clk %s\n",
-					__func__, parent->name, clk->name);
+					__func__, parent->name, core->name);
 			ret = p_index;
 			goto out;
 		}
 	}
 
 	/* propagate PRE_RATE_CHANGE notifications */
-	ret = __clk_speculate_rates(clk, p_rate);
+	ret = __clk_speculate_rates(core, p_rate);
 
 	/* abort if a driver objects */
 	if (ret & NOTIFY_STOP_MASK)
 		goto out;
 
 	/* do the re-parent */
-	ret = __clk_set_parent(clk, parent, p_index);
+	ret = __clk_set_parent(core, parent, p_index);
 
 	/* propagate rate an accuracy recalculation accordingly */
 	if (ret) {
-		__clk_recalc_rates(clk, ABORT_RATE_CHANGE);
+		__clk_recalc_rates(core, ABORT_RATE_CHANGE);
 	} else {
-		__clk_recalc_rates(clk, POST_RATE_CHANGE);
-		__clk_recalc_accuracies(clk);
+		__clk_recalc_rates(core, POST_RATE_CHANGE);
+		__clk_recalc_accuracies(core);
 	}
 
 out:
@@ -2193,15 +2193,15 @@ int clk_set_phase(struct clk *clk, int degrees)
 }
 EXPORT_SYMBOL_GPL(clk_set_phase);
 
-static int clk_core_get_phase(struct clk_core *clk)
+static int clk_core_get_phase(struct clk_core *core)
 {
 	int ret = 0;
 
-	if (!clk)
+	if (!core)
 		goto out;
 
 	clk_prepare_lock();
-	ret = clk->phase;
+	ret = core->phase;
 	clk_prepare_unlock();
 
 out:
@@ -2263,67 +2263,67 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
 	int i, ret = 0;
 	struct clk_core *orphan;
 	struct hlist_node *tmp2;
-	struct clk_core *clk;
+	struct clk_core *core;
 	unsigned long rate;
 
 	if (!clk_user)
 		return -EINVAL;
 
-	clk = clk_user->core;
+	core = clk_user->core;
 
 	clk_prepare_lock();
 
 	/* check to see if a clock with this name is already registered */
-	if (clk_core_lookup(clk->name)) {
+	if (clk_core_lookup(core->name)) {
 		pr_debug("%s: clk %s already initialized\n",
-				__func__, clk->name);
+				__func__, core->name);
 		ret = -EEXIST;
 		goto out;
 	}
 
 	/* check that clk_ops are sane.  See Documentation/clk.txt */
-	if (clk->ops->set_rate &&
-	    !((clk->ops->round_rate || clk->ops->determine_rate) &&
-	      clk->ops->recalc_rate)) {
+	if (core->ops->set_rate &&
+	    !((core->ops->round_rate || core->ops->determine_rate) &&
+	      core->ops->recalc_rate)) {
 		pr_warning("%s: %s must implement .round_rate or .determine_rate in addition to .recalc_rate\n",
-				__func__, clk->name);
+				__func__, core->name);
 		ret = -EINVAL;
 		goto out;
 	}
 
-	if (clk->ops->set_parent && !clk->ops->get_parent) {
+	if (core->ops->set_parent && !core->ops->get_parent) {
 		pr_warning("%s: %s must implement .get_parent & .set_parent\n",
-				__func__, clk->name);
+				__func__, core->name);
 		ret = -EINVAL;
 		goto out;
 	}
 
-	if (clk->ops->set_rate_and_parent &&
-			!(clk->ops->set_parent && clk->ops->set_rate)) {
+	if (core->ops->set_rate_and_parent &&
+			!(core->ops->set_parent && core->ops->set_rate)) {
 		pr_warn("%s: %s must implement .set_parent & .set_rate\n",
-				__func__, clk->name);
+				__func__, core->name);
 		ret = -EINVAL;
 		goto out;
 	}
 
 	/* throw a WARN if any entries in parent_names are NULL */
-	for (i = 0; i < clk->num_parents; i++)
-		WARN(!clk->parent_names[i],
+	for (i = 0; i < core->num_parents; i++)
+		WARN(!core->parent_names[i],
 				"%s: invalid NULL in %s's .parent_names\n",
-				__func__, clk->name);
+				__func__, core->name);
 
 	/*
 	 * Allocate an array of struct clk *'s to avoid unnecessary string
 	 * look-ups of clk's possible parents.  This can fail for clocks passed
-	 * in to clk_init during early boot; thus any access to clk->parents[]
+	 * in to clk_init during early boot; thus any access to core->parents[]
 	 * must always check for a NULL pointer and try to populate it if
 	 * necessary.
 	 *
-	 * If clk->parents is not NULL we skip this entire block.  This allows
-	 * for clock drivers to statically initialize clk->parents.
+	 * If core->parents is not NULL we skip this entire block.  This allows
+	 * for clock drivers to statically initialize core->parents.
 	 */
-	if (clk->num_parents > 1 && !clk->parents) {
-		clk->parents = kcalloc(clk->num_parents, sizeof(struct clk *),
+	if (core->num_parents > 1 && !core->parents) {
+		core->parents = kcalloc(core->num_parents, sizeof(struct clk *),
 					GFP_KERNEL);
 		/*
 		 * clk_core_lookup returns NULL for parents that have not been
@@ -2331,16 +2331,16 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
 		 * for a NULL pointer.  We can always perform lazy lookups for
 		 * missing parents later on.
 		 */
-		if (clk->parents)
-			for (i = 0; i < clk->num_parents; i++)
-				clk->parents[i] =
-					clk_core_lookup(clk->parent_names[i]);
+		if (core->parents)
+			for (i = 0; i < core->num_parents; i++)
+				core->parents[i] =
+					clk_core_lookup(core->parent_names[i]);
 	}
 
-	clk->parent = __clk_init_parent(clk);
+	core->parent = __clk_init_parent(core);
 
 	/*
-	 * Populate clk->parent if parent has already been __clk_init'd.  If
+	 * Populate core->parent if parent has already been __clk_init'd.  If
 	 * parent has not yet been __clk_init'd then place clk in the orphan
 	 * list.  If clk has set the CLK_IS_ROOT flag then place it in the root
 	 * clk list.
@@ -2349,13 +2349,13 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
 	 * clocks and re-parent any that are children of the clock currently
 	 * being clk_init'd.
 	 */
-	if (clk->parent)
-		hlist_add_head(&clk->child_node,
-				&clk->parent->children);
-	else if (clk->flags & CLK_IS_ROOT)
-		hlist_add_head(&clk->child_node, &clk_root_list);
+	if (core->parent)
+		hlist_add_head(&core->child_node,
+				&core->parent->children);
+	else if (core->flags & CLK_IS_ROOT)
+		hlist_add_head(&core->child_node, &clk_root_list);
 	else
-		hlist_add_head(&clk->child_node, &clk_orphan_list);
+		hlist_add_head(&core->child_node, &clk_orphan_list);
 
 	/*
 	 * Set clk's accuracy.  The preferred method is to use
@@ -2364,23 +2364,23 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
 	 * parent (or is orphaned) then accuracy is set to zero (perfect
 	 * clock).
 	 */
-	if (clk->ops->recalc_accuracy)
-		clk->accuracy = clk->ops->recalc_accuracy(clk->hw,
-					__clk_get_accuracy(clk->parent));
-	else if (clk->parent)
-		clk->accuracy = clk->parent->accuracy;
+	if (core->ops->recalc_accuracy)
+		core->accuracy = core->ops->recalc_accuracy(core->hw,
+					__clk_get_accuracy(core->parent));
+	else if (core->parent)
+		core->accuracy = core->parent->accuracy;
 	else
-		clk->accuracy = 0;
+		core->accuracy = 0;
 
 	/*
 	 * Set clk's phase.
 	 * Since a phase is by definition relative to its parent, just
 	 * query the current clock phase, or just assume it's in phase.
 	 */
-	if (clk->ops->get_phase)
-		clk->phase = clk->ops->get_phase(clk->hw);
+	if (core->ops->get_phase)
+		core->phase = core->ops->get_phase(core->hw);
 	else
-		clk->phase = 0;
+		core->phase = 0;
 
 	/*
 	 * Set clk's rate.  The preferred method is to use .recalc_rate.  For
@@ -2388,14 +2388,14 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
 	 * parent's rate.  If a clock doesn't have a parent (or is orphaned)
 	 * then rate is set to zero.
 	 */
-	if (clk->ops->recalc_rate)
-		rate = clk->ops->recalc_rate(clk->hw,
-				clk_core_get_rate_nolock(clk->parent));
-	else if (clk->parent)
-		rate = clk->parent->rate;
+	if (core->ops->recalc_rate)
+		rate = core->ops->recalc_rate(core->hw,
+				clk_core_get_rate_nolock(core->parent));
+	else if (core->parent)
+		rate = core->parent->rate;
 	else
 		rate = 0;
-	clk->rate = clk->req_rate = rate;
+	core->rate = core->req_rate = rate;
 
 	/*
 	 * walk the list of orphan clocks and reparent any that are children of
@@ -2404,14 +2404,14 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
 	hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
 		if (orphan->num_parents && orphan->ops->get_parent) {
 			i = orphan->ops->get_parent(orphan->hw);
-			if (!strcmp(clk->name, orphan->parent_names[i]))
-				clk_core_reparent(orphan, clk);
+			if (!strcmp(core->name, orphan->parent_names[i]))
+				clk_core_reparent(orphan, core);
 			continue;
 		}
 
 		for (i = 0; i < orphan->num_parents; i++)
-			if (!strcmp(clk->name, orphan->parent_names[i])) {
-				clk_core_reparent(orphan, clk);
+			if (!strcmp(core->name, orphan->parent_names[i])) {
+				clk_core_reparent(orphan, core);
 				break;
 			}
 	 }
@@ -2424,15 +2424,15 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
 	 * Please consider other ways of solving initialization problems before
 	 * using this callback, as its use is discouraged.
 	 */
-	if (clk->ops->init)
-		clk->ops->init(clk->hw);
+	if (core->ops->init)
+		core->ops->init(core->hw);
 
-	kref_init(&clk->ref);
+	kref_init(&core->ref);
 out:
 	clk_prepare_unlock();
 
 	if (!ret)
-		clk_debug_register(clk);
+		clk_debug_register(core);
 
 	return ret;
 }
@@ -2485,34 +2485,34 @@ void __clk_free_clk(struct clk *clk)
 struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 {
 	int i, ret;
-	struct clk_core *clk;
+	struct clk_core *core;
 
-	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
-	if (!clk) {
+	core = kzalloc(sizeof(*core), GFP_KERNEL);
+	if (!core) {
 		pr_err("%s: could not allocate clk\n", __func__);
 		ret = -ENOMEM;
 		goto fail_out;
 	}
 
-	clk->name = kstrdup_const(hw->init->name, GFP_KERNEL);
-	if (!clk->name) {
+	core->name = kstrdup_const(hw->init->name, GFP_KERNEL);
+	if (!core->name) {
 		pr_err("%s: could not allocate clk->name\n", __func__);
 		ret = -ENOMEM;
 		goto fail_name;
 	}
-	clk->ops = hw->init->ops;
+	core->ops = hw->init->ops;
 	if (dev && dev->driver)
-		clk->owner = dev->driver->owner;
-	clk->hw = hw;
-	clk->flags = hw->init->flags;
-	clk->num_parents = hw->init->num_parents;
-	hw->core = clk;
+		core->owner = dev->driver->owner;
+	core->hw = hw;
+	core->flags = hw->init->flags;
+	core->num_parents = hw->init->num_parents;
+	hw->core = core;
 
 	/* allocate local copy in case parent_names is __initdata */
-	clk->parent_names = kcalloc(clk->num_parents, sizeof(char *),
+	core->parent_names = kcalloc(core->num_parents, sizeof(char *),
 					GFP_KERNEL);
 
-	if (!clk->parent_names) {
+	if (!core->parent_names) {
 		pr_err("%s: could not allocate clk->parent_names\n", __func__);
 		ret = -ENOMEM;
 		goto fail_parent_names;
@@ -2520,17 +2520,17 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 
 
 	/* copy each string name in case parent_names is __initdata */
-	for (i = 0; i < clk->num_parents; i++) {
-		clk->parent_names[i] = kstrdup_const(hw->init->parent_names[i],
+	for (i = 0; i < core->num_parents; i++) {
+		core->parent_names[i] = kstrdup_const(hw->init->parent_names[i],
 						GFP_KERNEL);
-		if (!clk->parent_names[i]) {
+		if (!core->parent_names[i]) {
 			pr_err("%s: could not copy parent_names\n", __func__);
 			ret = -ENOMEM;
 			goto fail_parent_names_copy;
 		}
 	}
 
-	INIT_HLIST_HEAD(&clk->clks);
+	INIT_HLIST_HEAD(&core->clks);
 
 	hw->clk = __clk_create_clk(hw, NULL, NULL);
 	if (IS_ERR(hw->clk)) {
@@ -2548,12 +2548,12 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 
 fail_parent_names_copy:
 	while (--i >= 0)
-		kfree_const(clk->parent_names[i]);
-	kfree(clk->parent_names);
+		kfree_const(core->parent_names[i]);
+	kfree(core->parent_names);
 fail_parent_names:
-	kfree_const(clk->name);
+	kfree_const(core->name);
 fail_name:
-	kfree(clk);
+	kfree(core);
 fail_out:
 	return ERR_PTR(ret);
 }
@@ -2565,18 +2565,18 @@ EXPORT_SYMBOL_GPL(clk_register);
  */
 static void __clk_release(struct kref *ref)
 {
-	struct clk_core *clk = container_of(ref, struct clk_core, ref);
-	int i = clk->num_parents;
+	struct clk_core *core = container_of(ref, struct clk_core, ref);
+	int i = core->num_parents;
 
 	lockdep_assert_held(&prepare_lock);
 
-	kfree(clk->parents);
+	kfree(core->parents);
 	while (--i >= 0)
-		kfree_const(clk->parent_names[i]);
+		kfree_const(core->parent_names[i]);
 
-	kfree(clk->parent_names);
-	kfree_const(clk->name);
-	kfree(clk);
+	kfree(core->parent_names);
+	kfree_const(core->name);
+	kfree(core);
 }
 
 /*

From 864e160ae510f5223e7bd9aa4335d7e092173446 Mon Sep 17 00:00:00 2001
From: Dong Aisheng <aisheng.dong@freescale.com>
Date: Thu, 30 Apr 2015 14:02:19 -0700
Subject: [PATCH 002/135] clk: Squash __clk_{enable,disable}() into callers

These functions are only used in one place. Let's squash them
into their respective callers to save some lines.

Signed-off-by: Dong Aisheng <aisheng.dong@freescale.com>
[sboyd@codeaurora.org: Redo commit text, add NULL check in
clk_enable()]
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 23 +++++------------------
 1 file changed, 5 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0b3c914db1ca..88439af5d032 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1023,14 +1023,6 @@ static void clk_core_disable(struct clk_core *core)
 	clk_core_disable(core->parent);
 }
 
-static void __clk_disable(struct clk *clk)
-{
-	if (!clk)
-		return;
-
-	clk_core_disable(clk->core);
-}
-
 /**
  * clk_disable - gate a clock
  * @clk: the clk being gated
@@ -1051,7 +1043,7 @@ void clk_disable(struct clk *clk)
 		return;
 
 	flags = clk_enable_lock();
-	__clk_disable(clk);
+	clk_core_disable(clk->core);
 	clk_enable_unlock(flags);
 }
 EXPORT_SYMBOL_GPL(clk_disable);
@@ -1089,14 +1081,6 @@ static int clk_core_enable(struct clk_core *core)
 	return 0;
 }
 
-static int __clk_enable(struct clk *clk)
-{
-	if (!clk)
-		return 0;
-
-	return clk_core_enable(clk->core);
-}
-
 /**
  * clk_enable - ungate a clock
  * @clk: the clk being ungated
@@ -1115,8 +1099,11 @@ int clk_enable(struct clk *clk)
 	unsigned long flags;
 	int ret;
 
+	if (!clk)
+		return 0;
+
 	flags = clk_enable_lock();
-	ret = __clk_enable(clk);
+	ret = clk_core_enable(clk->core);
 	clk_enable_unlock(flags);
 
 	return ret;

From d7d131512b474c902b83a314d69a012e70c55431 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Thu, 30 Apr 2015 14:04:53 -0700
Subject: [PATCH 003/135] clk: Drop unnecessary OOM prints

We don't need to print error messages when allocations fail.
We'll get a nice backtrace in such situations anyway.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 88439af5d032..8d36100c00ce 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2476,14 +2476,12 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 
 	core = kzalloc(sizeof(*core), GFP_KERNEL);
 	if (!core) {
-		pr_err("%s: could not allocate clk\n", __func__);
 		ret = -ENOMEM;
 		goto fail_out;
 	}
 
 	core->name = kstrdup_const(hw->init->name, GFP_KERNEL);
 	if (!core->name) {
-		pr_err("%s: could not allocate clk->name\n", __func__);
 		ret = -ENOMEM;
 		goto fail_name;
 	}
@@ -2500,7 +2498,6 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 					GFP_KERNEL);
 
 	if (!core->parent_names) {
-		pr_err("%s: could not allocate clk->parent_names\n", __func__);
 		ret = -ENOMEM;
 		goto fail_parent_names;
 	}
@@ -2511,7 +2508,6 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 		core->parent_names[i] = kstrdup_const(hw->init->parent_names[i],
 						GFP_KERNEL);
 		if (!core->parent_names[i]) {
-			pr_err("%s: could not copy parent_names\n", __func__);
 			ret = -ENOMEM;
 			goto fail_parent_names_copy;
 		}
@@ -2521,7 +2517,6 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 
 	hw->clk = __clk_create_clk(hw, NULL, NULL);
 	if (IS_ERR(hw->clk)) {
-		pr_err("%s: could not allocate per-user clk\n", __func__);
 		ret = PTR_ERR(hw->clk);
 		goto fail_parent_names_copy;
 	}

From 1f3e1983429d31ceada9a09197d79445c92a2901 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Thu, 30 Apr 2015 14:21:56 -0700
Subject: [PATCH 004/135] clk: Remove impossible if condition in
 clk_core_get_phase()

This condition can't ever be true because this function is static
and it's always called with a non-NULL pointer.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 8d36100c00ce..3e58b7453076 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2182,16 +2182,12 @@ EXPORT_SYMBOL_GPL(clk_set_phase);
 
 static int clk_core_get_phase(struct clk_core *core)
 {
-	int ret = 0;
-
-	if (!core)
-		goto out;
+	int ret;
 
 	clk_prepare_lock();
 	ret = core->phase;
 	clk_prepare_unlock();
 
-out:
 	return ret;
 }
 EXPORT_SYMBOL_GPL(clk_get_phase);

From 4dff95dc9477a34de77d24c59dcf1dc593687fcf Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Thu, 30 Apr 2015 14:43:22 -0700
Subject: [PATCH 005/135] clk: Remove forward declared function prototypes

Move the code around so that we don't need to declare function
prototypes at the start of the file. Simplify
clk_core_is_prepared() and clk_core_is_enabled() too to make the
diff easier to read.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 811 ++++++++++++++++++++++------------------------
 1 file changed, 393 insertions(+), 418 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 3e58b7453076..0001b91f2b6e 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -37,13 +37,6 @@ static HLIST_HEAD(clk_root_list);
 static HLIST_HEAD(clk_orphan_list);
 static LIST_HEAD(clk_notifier_list);
 
-static long clk_core_get_accuracy(struct clk_core *core);
-static unsigned long clk_core_get_rate(struct clk_core *core);
-static int clk_core_get_phase(struct clk_core *core);
-static bool clk_core_is_prepared(struct clk_core *core);
-static bool clk_core_is_enabled(struct clk_core *core);
-static struct clk_core *clk_core_lookup(const char *name);
-
 /***    private data structures    ***/
 
 struct clk_core {
@@ -145,339 +138,30 @@ static void clk_enable_unlock(unsigned long flags)
 	spin_unlock_irqrestore(&enable_lock, flags);
 }
 
-/***        debugfs support        ***/
-
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
-
-static struct dentry *rootdir;
-static int inited = 0;
-static DEFINE_MUTEX(clk_debug_lock);
-static HLIST_HEAD(clk_debug_list);
-
-static struct hlist_head *all_lists[] = {
-	&clk_root_list,
-	&clk_orphan_list,
-	NULL,
-};
-
-static struct hlist_head *orphan_list[] = {
-	&clk_orphan_list,
-	NULL,
-};
-
-static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
-				 int level)
+static bool clk_core_is_prepared(struct clk_core *core)
 {
-	if (!c)
-		return;
+	/*
+	 * .is_prepared is optional for clocks that can prepare
+	 * fall back to software usage counter if it is missing
+	 */
+	if (!core->ops->is_prepared)
+		return core->prepare_count;
 
-	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
-		   level * 3 + 1, "",
-		   30 - level * 3, c->name,
-		   c->enable_count, c->prepare_count, clk_core_get_rate(c),
-		   clk_core_get_accuracy(c), clk_core_get_phase(c));
+	return core->ops->is_prepared(core->hw);
 }
 
-static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
-				     int level)
+static bool clk_core_is_enabled(struct clk_core *core)
 {
-	struct clk_core *child;
+	/*
+	 * .is_enabled is only mandatory for clocks that gate
+	 * fall back to software usage counter if .is_enabled is missing
+	 */
+	if (!core->ops->is_enabled)
+		return core->enable_count;
 
-	if (!c)
-		return;
-
-	clk_summary_show_one(s, c, level);
-
-	hlist_for_each_entry(child, &c->children, child_node)
-		clk_summary_show_subtree(s, child, level + 1);
+	return core->ops->is_enabled(core->hw);
 }
 
-static int clk_summary_show(struct seq_file *s, void *data)
-{
-	struct clk_core *c;
-	struct hlist_head **lists = (struct hlist_head **)s->private;
-
-	seq_puts(s, "   clock                         enable_cnt  prepare_cnt        rate   accuracy   phase\n");
-	seq_puts(s, "----------------------------------------------------------------------------------------\n");
-
-	clk_prepare_lock();
-
-	for (; *lists; lists++)
-		hlist_for_each_entry(c, *lists, child_node)
-			clk_summary_show_subtree(s, c, 0);
-
-	clk_prepare_unlock();
-
-	return 0;
-}
-
-
-static int clk_summary_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, clk_summary_show, inode->i_private);
-}
-
-static const struct file_operations clk_summary_fops = {
-	.open		= clk_summary_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
-{
-	if (!c)
-		return;
-
-	seq_printf(s, "\"%s\": { ", c->name);
-	seq_printf(s, "\"enable_count\": %d,", c->enable_count);
-	seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
-	seq_printf(s, "\"rate\": %lu", clk_core_get_rate(c));
-	seq_printf(s, "\"accuracy\": %lu", clk_core_get_accuracy(c));
-	seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
-}
-
-static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
-{
-	struct clk_core *child;
-
-	if (!c)
-		return;
-
-	clk_dump_one(s, c, level);
-
-	hlist_for_each_entry(child, &c->children, child_node) {
-		seq_printf(s, ",");
-		clk_dump_subtree(s, child, level + 1);
-	}
-
-	seq_printf(s, "}");
-}
-
-static int clk_dump(struct seq_file *s, void *data)
-{
-	struct clk_core *c;
-	bool first_node = true;
-	struct hlist_head **lists = (struct hlist_head **)s->private;
-
-	seq_printf(s, "{");
-
-	clk_prepare_lock();
-
-	for (; *lists; lists++) {
-		hlist_for_each_entry(c, *lists, child_node) {
-			if (!first_node)
-				seq_puts(s, ",");
-			first_node = false;
-			clk_dump_subtree(s, c, 0);
-		}
-	}
-
-	clk_prepare_unlock();
-
-	seq_printf(s, "}");
-	return 0;
-}
-
-
-static int clk_dump_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, clk_dump, inode->i_private);
-}
-
-static const struct file_operations clk_dump_fops = {
-	.open		= clk_dump_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
-{
-	struct dentry *d;
-	int ret = -ENOMEM;
-
-	if (!core || !pdentry) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	d = debugfs_create_dir(core->name, pdentry);
-	if (!d)
-		goto out;
-
-	core->dentry = d;
-
-	d = debugfs_create_u32("clk_rate", S_IRUGO, core->dentry,
-			(u32 *)&core->rate);
-	if (!d)
-		goto err_out;
-
-	d = debugfs_create_u32("clk_accuracy", S_IRUGO, core->dentry,
-			(u32 *)&core->accuracy);
-	if (!d)
-		goto err_out;
-
-	d = debugfs_create_u32("clk_phase", S_IRUGO, core->dentry,
-			(u32 *)&core->phase);
-	if (!d)
-		goto err_out;
-
-	d = debugfs_create_x32("clk_flags", S_IRUGO, core->dentry,
-			(u32 *)&core->flags);
-	if (!d)
-		goto err_out;
-
-	d = debugfs_create_u32("clk_prepare_count", S_IRUGO, core->dentry,
-			(u32 *)&core->prepare_count);
-	if (!d)
-		goto err_out;
-
-	d = debugfs_create_u32("clk_enable_count", S_IRUGO, core->dentry,
-			(u32 *)&core->enable_count);
-	if (!d)
-		goto err_out;
-
-	d = debugfs_create_u32("clk_notifier_count", S_IRUGO, core->dentry,
-			(u32 *)&core->notifier_count);
-	if (!d)
-		goto err_out;
-
-	if (core->ops->debug_init) {
-		ret = core->ops->debug_init(core->hw, core->dentry);
-		if (ret)
-			goto err_out;
-	}
-
-	ret = 0;
-	goto out;
-
-err_out:
-	debugfs_remove_recursive(core->dentry);
-	core->dentry = NULL;
-out:
-	return ret;
-}
-
-/**
- * clk_debug_register - add a clk node to the debugfs clk tree
- * @core: the clk being added to the debugfs clk tree
- *
- * Dynamically adds a clk to the debugfs clk tree if debugfs has been
- * initialized.  Otherwise it bails out early since the debugfs clk tree
- * will be created lazily by clk_debug_init as part of a late_initcall.
- */
-static int clk_debug_register(struct clk_core *core)
-{
-	int ret = 0;
-
-	mutex_lock(&clk_debug_lock);
-	hlist_add_head(&core->debug_node, &clk_debug_list);
-
-	if (!inited)
-		goto unlock;
-
-	ret = clk_debug_create_one(core, rootdir);
-unlock:
-	mutex_unlock(&clk_debug_lock);
-
-	return ret;
-}
-
- /**
- * clk_debug_unregister - remove a clk node from the debugfs clk tree
- * @core: the clk being removed from the debugfs clk tree
- *
- * Dynamically removes a clk and all it's children clk nodes from the
- * debugfs clk tree if clk->dentry points to debugfs created by
- * clk_debug_register in __clk_init.
- */
-static void clk_debug_unregister(struct clk_core *core)
-{
-	mutex_lock(&clk_debug_lock);
-	hlist_del_init(&core->debug_node);
-	debugfs_remove_recursive(core->dentry);
-	core->dentry = NULL;
-	mutex_unlock(&clk_debug_lock);
-}
-
-struct dentry *clk_debugfs_add_file(struct clk_hw *hw, char *name, umode_t mode,
-				void *data, const struct file_operations *fops)
-{
-	struct dentry *d = NULL;
-
-	if (hw->core->dentry)
-		d = debugfs_create_file(name, mode, hw->core->dentry, data,
-					fops);
-
-	return d;
-}
-EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
-
-/**
- * clk_debug_init - lazily create the debugfs clk tree visualization
- *
- * clks are often initialized very early during boot before memory can
- * be dynamically allocated and well before debugfs is setup.
- * clk_debug_init walks the clk tree hierarchy while holding
- * prepare_lock and creates the topology as part of a late_initcall,
- * thus insuring that clks initialized very early will still be
- * represented in the debugfs clk tree.  This function should only be
- * called once at boot-time, and all other clks added dynamically will
- * be done so with clk_debug_register.
- */
-static int __init clk_debug_init(void)
-{
-	struct clk_core *core;
-	struct dentry *d;
-
-	rootdir = debugfs_create_dir("clk", NULL);
-
-	if (!rootdir)
-		return -ENOMEM;
-
-	d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, &all_lists,
-				&clk_summary_fops);
-	if (!d)
-		return -ENOMEM;
-
-	d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, &all_lists,
-				&clk_dump_fops);
-	if (!d)
-		return -ENOMEM;
-
-	d = debugfs_create_file("clk_orphan_summary", S_IRUGO, rootdir,
-				&orphan_list, &clk_summary_fops);
-	if (!d)
-		return -ENOMEM;
-
-	d = debugfs_create_file("clk_orphan_dump", S_IRUGO, rootdir,
-				&orphan_list, &clk_dump_fops);
-	if (!d)
-		return -ENOMEM;
-
-	mutex_lock(&clk_debug_lock);
-	hlist_for_each_entry(core, &clk_debug_list, debug_node)
-		clk_debug_create_one(core, rootdir);
-
-	inited = 1;
-	mutex_unlock(&clk_debug_lock);
-
-	return 0;
-}
-late_initcall(clk_debug_init);
-#else
-static inline int clk_debug_register(struct clk_core *core) { return 0; }
-static inline void clk_debug_reparent(struct clk_core *core,
-				      struct clk_core *new_parent)
-{
-}
-static inline void clk_debug_unregister(struct clk_core *core)
-{
-}
-#endif
-
 /* caller must hold prepare_lock */
 static void clk_unprepare_unused_subtree(struct clk_core *core)
 {
@@ -608,6 +292,49 @@ struct clk *__clk_get_parent(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(__clk_get_parent);
 
+static struct clk_core *__clk_lookup_subtree(const char *name,
+					     struct clk_core *core)
+{
+	struct clk_core *child;
+	struct clk_core *ret;
+
+	if (!strcmp(core->name, name))
+		return core;
+
+	hlist_for_each_entry(child, &core->children, child_node) {
+		ret = __clk_lookup_subtree(name, child);
+		if (ret)
+			return ret;
+	}
+
+	return NULL;
+}
+
+static struct clk_core *clk_core_lookup(const char *name)
+{
+	struct clk_core *root_clk;
+	struct clk_core *ret;
+
+	if (!name)
+		return NULL;
+
+	/* search the 'proper' clk tree first */
+	hlist_for_each_entry(root_clk, &clk_root_list, child_node) {
+		ret = __clk_lookup_subtree(name, root_clk);
+		if (ret)
+			return ret;
+	}
+
+	/* if not found, then search the orphan tree */
+	hlist_for_each_entry(root_clk, &clk_orphan_list, child_node) {
+		ret = __clk_lookup_subtree(name, root_clk);
+		if (ret)
+			return ret;
+	}
+
+	return NULL;
+}
+
 static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core,
 							 u8 index)
 {
@@ -684,27 +411,6 @@ unsigned long __clk_get_flags(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(__clk_get_flags);
 
-static bool clk_core_is_prepared(struct clk_core *core)
-{
-	int ret;
-
-	if (!core)
-		return false;
-
-	/*
-	 * .is_prepared is optional for clocks that can prepare
-	 * fall back to software usage counter if it is missing
-	 */
-	if (!core->ops->is_prepared) {
-		ret = core->prepare_count ? 1 : 0;
-		goto out;
-	}
-
-	ret = core->ops->is_prepared(core->hw);
-out:
-	return !!ret;
-}
-
 bool __clk_is_prepared(struct clk *clk)
 {
 	if (!clk)
@@ -713,27 +419,6 @@ bool __clk_is_prepared(struct clk *clk)
 	return clk_core_is_prepared(clk->core);
 }
 
-static bool clk_core_is_enabled(struct clk_core *core)
-{
-	int ret;
-
-	if (!core)
-		return false;
-
-	/*
-	 * .is_enabled is only mandatory for clocks that gate
-	 * fall back to software usage counter if .is_enabled is missing
-	 */
-	if (!core->ops->is_enabled) {
-		ret = core->enable_count ? 1 : 0;
-		goto out;
-	}
-
-	ret = core->ops->is_enabled(core->hw);
-out:
-	return !!ret;
-}
-
 bool __clk_is_enabled(struct clk *clk)
 {
 	if (!clk)
@@ -743,49 +428,6 @@ bool __clk_is_enabled(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(__clk_is_enabled);
 
-static struct clk_core *__clk_lookup_subtree(const char *name,
-					     struct clk_core *core)
-{
-	struct clk_core *child;
-	struct clk_core *ret;
-
-	if (!strcmp(core->name, name))
-		return core;
-
-	hlist_for_each_entry(child, &core->children, child_node) {
-		ret = __clk_lookup_subtree(name, child);
-		if (ret)
-			return ret;
-	}
-
-	return NULL;
-}
-
-static struct clk_core *clk_core_lookup(const char *name)
-{
-	struct clk_core *root_clk;
-	struct clk_core *ret;
-
-	if (!name)
-		return NULL;
-
-	/* search the 'proper' clk tree first */
-	hlist_for_each_entry(root_clk, &clk_root_list, child_node) {
-		ret = __clk_lookup_subtree(name, root_clk);
-		if (ret)
-			return ret;
-	}
-
-	/* if not found, then search the orphan tree */
-	hlist_for_each_entry(root_clk, &clk_orphan_list, child_node) {
-		ret = __clk_lookup_subtree(name, root_clk);
-		if (ret)
-			return ret;
-	}
-
-	return NULL;
-}
-
 static bool mux_is_better_rate(unsigned long rate, unsigned long now,
 			   unsigned long best, unsigned long flags)
 {
@@ -2190,7 +1832,6 @@ static int clk_core_get_phase(struct clk_core *core)
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(clk_get_phase);
 
 /**
  * clk_get_phase - return the phase shift of a clock signal
@@ -2206,6 +1847,7 @@ int clk_get_phase(struct clk *clk)
 
 	return clk_core_get_phase(clk->core);
 }
+EXPORT_SYMBOL_GPL(clk_get_phase);
 
 /**
  * clk_is_match - check if two clk's point to the same hardware clock
@@ -2233,6 +1875,339 @@ bool clk_is_match(const struct clk *p, const struct clk *q)
 }
 EXPORT_SYMBOL_GPL(clk_is_match);
 
+/***        debugfs support        ***/
+
+#ifdef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+
+static struct dentry *rootdir;
+static int inited = 0;
+static DEFINE_MUTEX(clk_debug_lock);
+static HLIST_HEAD(clk_debug_list);
+
+static struct hlist_head *all_lists[] = {
+	&clk_root_list,
+	&clk_orphan_list,
+	NULL,
+};
+
+static struct hlist_head *orphan_list[] = {
+	&clk_orphan_list,
+	NULL,
+};
+
+static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
+				 int level)
+{
+	if (!c)
+		return;
+
+	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
+		   level * 3 + 1, "",
+		   30 - level * 3, c->name,
+		   c->enable_count, c->prepare_count, clk_core_get_rate(c),
+		   clk_core_get_accuracy(c), clk_core_get_phase(c));
+}
+
+static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
+				     int level)
+{
+	struct clk_core *child;
+
+	if (!c)
+		return;
+
+	clk_summary_show_one(s, c, level);
+
+	hlist_for_each_entry(child, &c->children, child_node)
+		clk_summary_show_subtree(s, child, level + 1);
+}
+
+static int clk_summary_show(struct seq_file *s, void *data)
+{
+	struct clk_core *c;
+	struct hlist_head **lists = (struct hlist_head **)s->private;
+
+	seq_puts(s, "   clock                         enable_cnt  prepare_cnt        rate   accuracy   phase\n");
+	seq_puts(s, "----------------------------------------------------------------------------------------\n");
+
+	clk_prepare_lock();
+
+	for (; *lists; lists++)
+		hlist_for_each_entry(c, *lists, child_node)
+			clk_summary_show_subtree(s, c, 0);
+
+	clk_prepare_unlock();
+
+	return 0;
+}
+
+
+static int clk_summary_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, clk_summary_show, inode->i_private);
+}
+
+static const struct file_operations clk_summary_fops = {
+	.open		= clk_summary_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
+{
+	if (!c)
+		return;
+
+	seq_printf(s, "\"%s\": { ", c->name);
+	seq_printf(s, "\"enable_count\": %d,", c->enable_count);
+	seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
+	seq_printf(s, "\"rate\": %lu", clk_core_get_rate(c));
+	seq_printf(s, "\"accuracy\": %lu", clk_core_get_accuracy(c));
+	seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
+}
+
+static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
+{
+	struct clk_core *child;
+
+	if (!c)
+		return;
+
+	clk_dump_one(s, c, level);
+
+	hlist_for_each_entry(child, &c->children, child_node) {
+		seq_printf(s, ",");
+		clk_dump_subtree(s, child, level + 1);
+	}
+
+	seq_printf(s, "}");
+}
+
+static int clk_dump(struct seq_file *s, void *data)
+{
+	struct clk_core *c;
+	bool first_node = true;
+	struct hlist_head **lists = (struct hlist_head **)s->private;
+
+	seq_printf(s, "{");
+
+	clk_prepare_lock();
+
+	for (; *lists; lists++) {
+		hlist_for_each_entry(c, *lists, child_node) {
+			if (!first_node)
+				seq_puts(s, ",");
+			first_node = false;
+			clk_dump_subtree(s, c, 0);
+		}
+	}
+
+	clk_prepare_unlock();
+
+	seq_printf(s, "}");
+	return 0;
+}
+
+
+static int clk_dump_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, clk_dump, inode->i_private);
+}
+
+static const struct file_operations clk_dump_fops = {
+	.open		= clk_dump_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
+{
+	struct dentry *d;
+	int ret = -ENOMEM;
+
+	if (!core || !pdentry) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	d = debugfs_create_dir(core->name, pdentry);
+	if (!d)
+		goto out;
+
+	core->dentry = d;
+
+	d = debugfs_create_u32("clk_rate", S_IRUGO, core->dentry,
+			(u32 *)&core->rate);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("clk_accuracy", S_IRUGO, core->dentry,
+			(u32 *)&core->accuracy);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("clk_phase", S_IRUGO, core->dentry,
+			(u32 *)&core->phase);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_x32("clk_flags", S_IRUGO, core->dentry,
+			(u32 *)&core->flags);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("clk_prepare_count", S_IRUGO, core->dentry,
+			(u32 *)&core->prepare_count);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("clk_enable_count", S_IRUGO, core->dentry,
+			(u32 *)&core->enable_count);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("clk_notifier_count", S_IRUGO, core->dentry,
+			(u32 *)&core->notifier_count);
+	if (!d)
+		goto err_out;
+
+	if (core->ops->debug_init) {
+		ret = core->ops->debug_init(core->hw, core->dentry);
+		if (ret)
+			goto err_out;
+	}
+
+	ret = 0;
+	goto out;
+
+err_out:
+	debugfs_remove_recursive(core->dentry);
+	core->dentry = NULL;
+out:
+	return ret;
+}
+
+/**
+ * clk_debug_register - add a clk node to the debugfs clk tree
+ * @core: the clk being added to the debugfs clk tree
+ *
+ * Dynamically adds a clk to the debugfs clk tree if debugfs has been
+ * initialized.  Otherwise it bails out early since the debugfs clk tree
+ * will be created lazily by clk_debug_init as part of a late_initcall.
+ */
+static int clk_debug_register(struct clk_core *core)
+{
+	int ret = 0;
+
+	mutex_lock(&clk_debug_lock);
+	hlist_add_head(&core->debug_node, &clk_debug_list);
+
+	if (!inited)
+		goto unlock;
+
+	ret = clk_debug_create_one(core, rootdir);
+unlock:
+	mutex_unlock(&clk_debug_lock);
+
+	return ret;
+}
+
+ /**
+ * clk_debug_unregister - remove a clk node from the debugfs clk tree
+ * @core: the clk being removed from the debugfs clk tree
+ *
+ * Dynamically removes a clk and all it's children clk nodes from the
+ * debugfs clk tree if clk->dentry points to debugfs created by
+ * clk_debug_register in __clk_init.
+ */
+static void clk_debug_unregister(struct clk_core *core)
+{
+	mutex_lock(&clk_debug_lock);
+	hlist_del_init(&core->debug_node);
+	debugfs_remove_recursive(core->dentry);
+	core->dentry = NULL;
+	mutex_unlock(&clk_debug_lock);
+}
+
+struct dentry *clk_debugfs_add_file(struct clk_hw *hw, char *name, umode_t mode,
+				void *data, const struct file_operations *fops)
+{
+	struct dentry *d = NULL;
+
+	if (hw->core->dentry)
+		d = debugfs_create_file(name, mode, hw->core->dentry, data,
+					fops);
+
+	return d;
+}
+EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
+
+/**
+ * clk_debug_init - lazily create the debugfs clk tree visualization
+ *
+ * clks are often initialized very early during boot before memory can
+ * be dynamically allocated and well before debugfs is setup.
+ * clk_debug_init walks the clk tree hierarchy while holding
+ * prepare_lock and creates the topology as part of a late_initcall,
+ * thus insuring that clks initialized very early will still be
+ * represented in the debugfs clk tree.  This function should only be
+ * called once at boot-time, and all other clks added dynamically will
+ * be done so with clk_debug_register.
+ */
+static int __init clk_debug_init(void)
+{
+	struct clk_core *core;
+	struct dentry *d;
+
+	rootdir = debugfs_create_dir("clk", NULL);
+
+	if (!rootdir)
+		return -ENOMEM;
+
+	d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, &all_lists,
+				&clk_summary_fops);
+	if (!d)
+		return -ENOMEM;
+
+	d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, &all_lists,
+				&clk_dump_fops);
+	if (!d)
+		return -ENOMEM;
+
+	d = debugfs_create_file("clk_orphan_summary", S_IRUGO, rootdir,
+				&orphan_list, &clk_summary_fops);
+	if (!d)
+		return -ENOMEM;
+
+	d = debugfs_create_file("clk_orphan_dump", S_IRUGO, rootdir,
+				&orphan_list, &clk_dump_fops);
+	if (!d)
+		return -ENOMEM;
+
+	mutex_lock(&clk_debug_lock);
+	hlist_for_each_entry(core, &clk_debug_list, debug_node)
+		clk_debug_create_one(core, rootdir);
+
+	inited = 1;
+	mutex_unlock(&clk_debug_lock);
+
+	return 0;
+}
+late_initcall(clk_debug_init);
+#else
+static inline int clk_debug_register(struct clk_core *core) { return 0; }
+static inline void clk_debug_reparent(struct clk_core *core,
+				      struct clk_core *new_parent)
+{
+}
+static inline void clk_debug_unregister(struct clk_core *core)
+{
+}
+#endif
+
 /**
  * __clk_init - initialize the data structures in a struct clk
  * @dev:	device initializing this clk, placeholder for now

From 6e5ab41b1064eee6e3477f573370b2dda7d82bb7 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Thu, 30 Apr 2015 15:11:31 -0700
Subject: [PATCH 006/135] clk: Update some comments to reflect reality

The debugfs clk directory no longer expresses a clk tree. Update
the comments around that apporiately. Also drop comments about
prepare locks needing to be held as we have the proper
annotations with lockdep_assert_held().

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 51 +++++++++++++++++------------------------------
 1 file changed, 18 insertions(+), 33 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0001b91f2b6e..43b7e7227056 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -162,7 +162,6 @@ static bool clk_core_is_enabled(struct clk_core *core)
 	return core->ops->is_enabled(core->hw);
 }
 
-/* caller must hold prepare_lock */
 static void clk_unprepare_unused_subtree(struct clk_core *core)
 {
 	struct clk_core *child;
@@ -188,7 +187,6 @@ static void clk_unprepare_unused_subtree(struct clk_core *core)
 	}
 }
 
-/* caller must hold prepare_lock */
 static void clk_disable_unused_subtree(struct clk_core *core)
 {
 	struct clk_core *child;
@@ -791,8 +789,7 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
  * @min_rate: returned rate must be greater than this rate
  * @max_rate: returned rate must be less than this rate
  *
- * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate and
- * .determine_rate.
+ * Useful for clk_ops such as .set_rate and .determine_rate.
  */
 unsigned long __clk_determine_rate(struct clk_hw *hw,
 				   unsigned long rate,
@@ -811,7 +808,7 @@ EXPORT_SYMBOL_GPL(__clk_determine_rate);
  * @clk: round the rate of this clock
  * @rate: the rate which is to be rounded
  *
- * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
+ * Useful for clk_ops such as .set_rate
  */
 unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
 {
@@ -892,10 +889,8 @@ static int __clk_notify(struct clk_core *core, unsigned long msg,
  *
  * Walks the subtree of clks starting with clk and recalculates accuracies as
  * it goes.  Note that if a clk does not implement the .recalc_accuracy
- * callback then it is assumed that the clock will take on the accuracy of it's
+ * callback then it is assumed that the clock will take on the accuracy of its
  * parent.
- *
- * Caller must hold prepare_lock.
  */
 static void __clk_recalc_accuracies(struct clk_core *core)
 {
@@ -968,8 +963,6 @@ static unsigned long clk_recalc(struct clk_core *core,
  *
  * clk_recalc_rates also propagates the POST_RATE_CHANGE notification,
  * if necessary.
- *
- * Caller must hold prepare_lock.
  */
 static void __clk_recalc_rates(struct clk_core *core, unsigned long msg)
 {
@@ -1179,8 +1172,6 @@ static int __clk_set_parent(struct clk_core *core, struct clk_core *parent,
  * subtree have subscribed to the notifications.  Note that if a clk does not
  * implement the .recalc_rate callback then it is assumed that the clock will
  * take on the rate of its parent.
- *
- * Caller must hold prepare_lock.
  */
 static int __clk_speculate_rates(struct clk_core *core,
 				 unsigned long parent_rate)
@@ -2091,11 +2082,11 @@ out:
 }
 
 /**
- * clk_debug_register - add a clk node to the debugfs clk tree
- * @core: the clk being added to the debugfs clk tree
+ * clk_debug_register - add a clk node to the debugfs clk directory
+ * @core: the clk being added to the debugfs clk directory
  *
- * Dynamically adds a clk to the debugfs clk tree if debugfs has been
- * initialized.  Otherwise it bails out early since the debugfs clk tree
+ * Dynamically adds a clk to the debugfs clk directory if debugfs has been
+ * initialized.  Otherwise it bails out early since the debugfs clk directory
  * will be created lazily by clk_debug_init as part of a late_initcall.
  */
 static int clk_debug_register(struct clk_core *core)
@@ -2116,11 +2107,11 @@ unlock:
 }
 
  /**
- * clk_debug_unregister - remove a clk node from the debugfs clk tree
- * @core: the clk being removed from the debugfs clk tree
+ * clk_debug_unregister - remove a clk node from the debugfs clk directory
+ * @core: the clk being removed from the debugfs clk directory
  *
- * Dynamically removes a clk and all it's children clk nodes from the
- * debugfs clk tree if clk->dentry points to debugfs created by
+ * Dynamically removes a clk and all its child nodes from the
+ * debugfs clk directory if clk->dentry points to debugfs created by
  * clk_debug_register in __clk_init.
  */
 static void clk_debug_unregister(struct clk_core *core)
@@ -2146,16 +2137,13 @@ struct dentry *clk_debugfs_add_file(struct clk_hw *hw, char *name, umode_t mode,
 EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
 
 /**
- * clk_debug_init - lazily create the debugfs clk tree visualization
+ * clk_debug_init - lazily populate the debugfs clk directory
  *
- * clks are often initialized very early during boot before memory can
- * be dynamically allocated and well before debugfs is setup.
- * clk_debug_init walks the clk tree hierarchy while holding
- * prepare_lock and creates the topology as part of a late_initcall,
- * thus insuring that clks initialized very early will still be
- * represented in the debugfs clk tree.  This function should only be
- * called once at boot-time, and all other clks added dynamically will
- * be done so with clk_debug_register.
+ * clks are often initialized very early during boot before memory can be
+ * dynamically allocated and well before debugfs is setup. This function
+ * populates the debugfs clk directory once at boot-time when we know that
+ * debugfs is setup. It should only be called once at boot-time, all other clks
+ * added dynamically will be done so with clk_debug_register.
  */
 static int __init clk_debug_init(void)
 {
@@ -2512,10 +2500,7 @@ fail_out:
 }
 EXPORT_SYMBOL_GPL(clk_register);
 
-/*
- * Free memory allocated for a clock.
- * Caller must hold prepare_lock.
- */
+/* Free memory allocated for a clock. */
 static void __clk_release(struct kref *ref)
 {
 	struct clk_core *core = container_of(ref, struct clk_core, ref);

From 7cb81136d2efe0f5ed9d965857f4756a15e6c338 Mon Sep 17 00:00:00 2001
From: Stefan Wahren <stefan.wahren@i2se.com>
Date: Wed, 29 Apr 2015 16:36:43 +0000
Subject: [PATCH 007/135] clk: Fix JSON output in debugfs

key/value pairs in a JSON object must be separated by a comma.
After adding the properties "accuracy" and "phase" the JSON output
of /sys/kernel/debug/clk/clk_dump is invalid.

So add the missing commas to fix it.

Fixes: 5279fc402ae5 ("clk: add clk accuracy retrieval support")
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
[sboyd@codeaurora.org: Added comment in function]
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 43b7e7227056..ea7e8695a32b 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1951,11 +1951,12 @@ static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
 	if (!c)
 		return;
 
+	/* This should be JSON format, i.e. elements separated with a comma */
 	seq_printf(s, "\"%s\": { ", c->name);
 	seq_printf(s, "\"enable_count\": %d,", c->enable_count);
 	seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
-	seq_printf(s, "\"rate\": %lu", clk_core_get_rate(c));
-	seq_printf(s, "\"accuracy\": %lu", clk_core_get_accuracy(c));
+	seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
+	seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
 	seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
 }
 

From d6c27678676abd13f5457490a30995524e1046fb Mon Sep 17 00:00:00 2001
From: Krzysztof Kozlowski <k.kozlowski.k@gmail.com>
Date: Mon, 27 Apr 2015 21:52:38 +0900
Subject: [PATCH 008/135] clk: at91: Constify irq_domain_ops

The irq_domain_ops are not modified by the driver and the irqdomain core
code accepts pointer to a const data.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski.k@gmail.com>
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/at91/pmc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 3f27d21fb729..39be2be82b0a 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -153,7 +153,7 @@ static int pmc_irq_domain_xlate(struct irq_domain *d,
 	return 0;
 }
 
-static struct irq_domain_ops pmc_irq_ops = {
+static const struct irq_domain_ops pmc_irq_ops = {
 	.map	= pmc_irq_map,
 	.xlate	= pmc_irq_domain_xlate,
 };

From 5ac382c311fc12ccfb74832afe545ce8c38cc459 Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Sat, 2 May 2015 17:03:22 +0200
Subject: [PATCH 009/135] clk: sunxi: Fix of_io_request_and_map error check

of_io_request_and map returns an error pointer, but the current code assumes
that on error the returned pointer will be NULL.

Obviously, that makes the check completely useless. Change the test to actually
check for the proper error code.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: linux-clk@vger.kernel.org
---
 drivers/clk/sunxi/clk-sun9i-core.c | 10 +++++-----
 drivers/clk/sunxi/clk-sunxi.c      |  2 ++
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/sunxi/clk-sun9i-core.c b/drivers/clk/sunxi/clk-sun9i-core.c
index d8da77d72861..887f4ea161bb 100644
--- a/drivers/clk/sunxi/clk-sun9i-core.c
+++ b/drivers/clk/sunxi/clk-sun9i-core.c
@@ -93,7 +93,7 @@ static void __init sun9i_a80_pll4_setup(struct device_node *node)
 	void __iomem *reg;
 
 	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
-	if (!reg) {
+	if (IS_ERR(reg)) {
 		pr_err("Could not get registers for a80-pll4-clk: %s\n",
 		       node->name);
 		return;
@@ -154,7 +154,7 @@ static void __init sun9i_a80_gt_setup(struct device_node *node)
 	struct clk *gt;
 
 	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
-	if (!reg) {
+	if (IS_ERR(reg)) {
 		pr_err("Could not get registers for a80-gt-clk: %s\n",
 		       node->name);
 		return;
@@ -218,7 +218,7 @@ static void __init sun9i_a80_ahb_setup(struct device_node *node)
 	void __iomem *reg;
 
 	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
-	if (!reg) {
+	if (IS_ERR(reg)) {
 		pr_err("Could not get registers for a80-ahb-clk: %s\n",
 		       node->name);
 		return;
@@ -244,7 +244,7 @@ static void __init sun9i_a80_apb0_setup(struct device_node *node)
 	void __iomem *reg;
 
 	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
-	if (!reg) {
+	if (IS_ERR(reg)) {
 		pr_err("Could not get registers for a80-apb0-clk: %s\n",
 		       node->name);
 		return;
@@ -310,7 +310,7 @@ static void __init sun9i_a80_apb1_setup(struct device_node *node)
 	void __iomem *reg;
 
 	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
-	if (!reg) {
+	if (IS_ERR(reg)) {
 		pr_err("Could not get registers for a80-apb1-clk: %s\n",
 		       node->name);
 		return;
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 7e1e2bd189b6..9a82f17d2d73 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -198,6 +198,8 @@ static void __init sun6i_ahb1_clk_setup(struct device_node *node)
 	int i = 0;
 
 	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+	if (IS_ERR(reg))
+		return;
 
 	/* we have a mux, we will have >1 parents */
 	while (i < SUN6I_AHB1_MAX_PARENTS &&

From 2893c379461a208b3059f55dfe4dafa06b4aa46a Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer@pengutronix.de>
Date: Tue, 31 Mar 2015 20:16:52 +0200
Subject: [PATCH 010/135] clk: make strings in parent name arrays const
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The clk functions and structs declare the parent_name arrays as
'const char **parent_names' which means the parent name strings
are const, but the array itself is not. Use
'const char * const * parent_names' instead which also makes
the array const. This allows us to put the parent_name arrays into
the __initconst section.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Tested-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
[sboyd@codeaurora.org: Squelch 80-character checkpatch warnings]
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-composite.c  |  2 +-
 drivers/clk/clk-mux.c        |  6 ++++--
 include/linux/clk-provider.h | 10 ++++++----
 3 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 956b7e54fa1c..077f4c7148f1 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -188,7 +188,7 @@ static void clk_composite_disable(struct clk_hw *hw)
 }
 
 struct clk *clk_register_composite(struct device *dev, const char *name,
-			const char **parent_names, int num_parents,
+			const char * const *parent_names, int num_parents,
 			struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
 			struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
 			struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 69a094c3783d..6066a01b20ea 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -114,7 +114,8 @@ const struct clk_ops clk_mux_ro_ops = {
 EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
 
 struct clk *clk_register_mux_table(struct device *dev, const char *name,
-		const char **parent_names, u8 num_parents, unsigned long flags,
+		const char * const *parent_names, u8 num_parents,
+		unsigned long flags,
 		void __iomem *reg, u8 shift, u32 mask,
 		u8 clk_mux_flags, u32 *table, spinlock_t *lock)
 {
@@ -166,7 +167,8 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
 EXPORT_SYMBOL_GPL(clk_register_mux_table);
 
 struct clk *clk_register_mux(struct device *dev, const char *name,
-		const char **parent_names, u8 num_parents, unsigned long flags,
+		const char * const *parent_names, u8 num_parents,
+		unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_mux_flags, spinlock_t *lock)
 {
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index df695313f975..5378c2aba4d2 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -209,7 +209,7 @@ struct clk_ops {
 struct clk_init_data {
 	const char		*name;
 	const struct clk_ops	*ops;
-	const char		**parent_names;
+	const char		* const *parent_names;
 	u8			num_parents;
 	unsigned long		flags;
 };
@@ -426,12 +426,14 @@ extern const struct clk_ops clk_mux_ops;
 extern const struct clk_ops clk_mux_ro_ops;
 
 struct clk *clk_register_mux(struct device *dev, const char *name,
-		const char **parent_names, u8 num_parents, unsigned long flags,
+		const char * const *parent_names, u8 num_parents,
+		unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_mux_flags, spinlock_t *lock);
 
 struct clk *clk_register_mux_table(struct device *dev, const char *name,
-		const char **parent_names, u8 num_parents, unsigned long flags,
+		const char * const *parent_names, u8 num_parents,
+		unsigned long flags,
 		void __iomem *reg, u8 shift, u32 mask,
 		u8 clk_mux_flags, u32 *table, spinlock_t *lock);
 
@@ -518,7 +520,7 @@ struct clk_composite {
 };
 
 struct clk *clk_register_composite(struct device *dev, const char *name,
-		const char **parent_names, int num_parents,
+		const char * const *parent_names, int num_parents,
 		struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
 		struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
 		struct clk_hw *gate_hw, const struct clk_ops *gate_ops,

From 9741b1a68035b541005db1a4d7623bd9b3522ab4 Mon Sep 17 00:00:00 2001
From: James Liao <jamesjj.liao@mediatek.com>
Date: Thu, 23 Apr 2015 10:35:39 +0200
Subject: [PATCH 011/135] clk: mediatek: Add initial common clock support for
 Mediatek SoCs.

This patch adds common clock support for Mediatek SoCs, including plls,
muxes and clock gates.

Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
[sboyd@codeaurora.org: Squelch checkpatch warning in clk-mtk.h]
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/Makefile            |   1 +
 drivers/clk/mediatek/Makefile   |   1 +
 drivers/clk/mediatek/clk-gate.c | 137 +++++++++++++
 drivers/clk/mediatek/clk-gate.h |  49 +++++
 drivers/clk/mediatek/clk-mtk.c  | 220 +++++++++++++++++++++
 drivers/clk/mediatek/clk-mtk.h  | 159 +++++++++++++++
 drivers/clk/mediatek/clk-pll.c  | 332 ++++++++++++++++++++++++++++++++
 7 files changed, 899 insertions(+)
 create mode 100644 drivers/clk/mediatek/Makefile
 create mode 100644 drivers/clk/mediatek/clk-gate.c
 create mode 100644 drivers/clk/mediatek/clk-gate.h
 create mode 100644 drivers/clk/mediatek/clk-mtk.c
 create mode 100644 drivers/clk/mediatek/clk-mtk.h
 create mode 100644 drivers/clk/mediatek/clk-pll.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 3d00c25382c5..d965b3f6a372 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_ARCH_HI3xxx)		+= hisilicon/
 obj-$(CONFIG_ARCH_HIP04)		+= hisilicon/
 obj-$(CONFIG_ARCH_HIX5HD2)		+= hisilicon/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
+obj-$(CONFIG_ARCH_MEDIATEK)		+= mediatek/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)			+= mmp/
 endif
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
new file mode 100644
index 000000000000..c384e9778d1a
--- /dev/null
+++ b/drivers/clk/mediatek/Makefile
@@ -0,0 +1 @@
+obj-y += clk-mtk.o clk-pll.o clk-gate.o
diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
new file mode 100644
index 000000000000..9d77ee3256f2
--- /dev/null
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/clkdev.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+static int mtk_cg_bit_is_cleared(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+	u32 val;
+
+	regmap_read(cg->regmap, cg->sta_ofs, &val);
+
+	val &= BIT(cg->bit);
+
+	return val == 0;
+}
+
+static int mtk_cg_bit_is_set(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+	u32 val;
+
+	regmap_read(cg->regmap, cg->sta_ofs, &val);
+
+	val &= BIT(cg->bit);
+
+	return val != 0;
+}
+
+static void mtk_cg_set_bit(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+
+	regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit));
+}
+
+static void mtk_cg_clr_bit(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_clk_gate(hw);
+
+	regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
+}
+
+static int mtk_cg_enable(struct clk_hw *hw)
+{
+	mtk_cg_clr_bit(hw);
+
+	return 0;
+}
+
+static void mtk_cg_disable(struct clk_hw *hw)
+{
+	mtk_cg_set_bit(hw);
+}
+
+static int mtk_cg_enable_inv(struct clk_hw *hw)
+{
+	mtk_cg_set_bit(hw);
+
+	return 0;
+}
+
+static void mtk_cg_disable_inv(struct clk_hw *hw)
+{
+	mtk_cg_clr_bit(hw);
+}
+
+const struct clk_ops mtk_clk_gate_ops_setclr = {
+	.is_enabled	= mtk_cg_bit_is_cleared,
+	.enable		= mtk_cg_enable,
+	.disable	= mtk_cg_disable,
+};
+
+const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
+	.is_enabled	= mtk_cg_bit_is_set,
+	.enable		= mtk_cg_enable_inv,
+	.disable	= mtk_cg_disable_inv,
+};
+
+struct clk *mtk_clk_register_gate(
+		const char *name,
+		const char *parent_name,
+		struct regmap *regmap,
+		int set_ofs,
+		int clr_ofs,
+		int sta_ofs,
+		u8 bit,
+		const struct clk_ops *ops)
+{
+	struct mtk_clk_gate *cg;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	cg = kzalloc(sizeof(*cg), GFP_KERNEL);
+	if (!cg)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+	init.ops = ops;
+
+	cg->regmap = regmap;
+	cg->set_ofs = set_ofs;
+	cg->clr_ofs = clr_ofs;
+	cg->sta_ofs = sta_ofs;
+	cg->bit = bit;
+
+	cg->hw.init = &init;
+
+	clk = clk_register(NULL, &cg->hw);
+	if (IS_ERR(clk))
+		kfree(cg);
+
+	return clk;
+}
diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h
new file mode 100644
index 000000000000..6b6780b1e9c5
--- /dev/null
+++ b/drivers/clk/mediatek/clk-gate.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DRV_CLK_GATE_H
+#define __DRV_CLK_GATE_H
+
+#include <linux/regmap.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+struct mtk_clk_gate {
+	struct clk_hw	hw;
+	struct regmap	*regmap;
+	int		set_ofs;
+	int		clr_ofs;
+	int		sta_ofs;
+	u8		bit;
+};
+
+static inline struct mtk_clk_gate *to_clk_gate(struct clk_hw *hw)
+{
+	return container_of(hw, struct mtk_clk_gate, hw);
+}
+
+extern const struct clk_ops mtk_clk_gate_ops_setclr;
+extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
+
+struct clk *mtk_clk_register_gate(
+		const char *name,
+		const char *parent_name,
+		struct regmap *regmap,
+		int set_ofs,
+		int clr_ofs,
+		int sta_ofs,
+		u8 bit,
+		const struct clk_ops *ops);
+
+#endif /* __DRV_CLK_GATE_H */
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
new file mode 100644
index 000000000000..18444aea63c9
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/clkdev.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
+{
+	int i;
+	struct clk_onecell_data *clk_data;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return NULL;
+
+	clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL);
+	if (!clk_data->clks)
+		goto err_out;
+
+	clk_data->clk_num = clk_num;
+
+	for (i = 0; i < clk_num; i++)
+		clk_data->clks[i] = ERR_PTR(-ENOENT);
+
+	return clk_data;
+err_out:
+	kfree(clk_data);
+
+	return NULL;
+}
+
+void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
+		struct clk_onecell_data *clk_data)
+{
+	int i;
+	struct clk *clk;
+
+	for (i = 0; i < num; i++) {
+		const struct mtk_fixed_factor *ff = &clks[i];
+
+		clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
+				CLK_SET_RATE_PARENT, ff->mult, ff->div);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					ff->name, PTR_ERR(clk));
+			continue;
+		}
+
+		if (clk_data)
+			clk_data->clks[ff->id] = clk;
+	}
+}
+
+int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
+		int num, struct clk_onecell_data *clk_data)
+{
+	int i;
+	struct clk *clk;
+	struct regmap *regmap;
+
+	if (!clk_data)
+		return -ENOMEM;
+
+	regmap = syscon_node_to_regmap(node);
+	if (IS_ERR(regmap)) {
+		pr_err("Cannot find regmap for %s: %ld\n", node->full_name,
+				PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	for (i = 0; i < num; i++) {
+		const struct mtk_gate *gate = &clks[i];
+
+		clk = mtk_clk_register_gate(gate->name, gate->parent_name,
+				regmap,
+				gate->regs->set_ofs,
+				gate->regs->clr_ofs,
+				gate->regs->sta_ofs,
+				gate->shift, gate->ops);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					gate->name, PTR_ERR(clk));
+			continue;
+		}
+
+		clk_data->clks[gate->id] = clk;
+	}
+
+	return 0;
+}
+
+struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
+		void __iomem *base, spinlock_t *lock)
+{
+	struct clk *clk;
+	struct clk_mux *mux = NULL;
+	struct clk_gate *gate = NULL;
+	struct clk_divider *div = NULL;
+	struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;
+	const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL;
+	const char * const *parent_names;
+	const char *parent;
+	int num_parents;
+	int ret;
+
+	if (mc->mux_shift >= 0) {
+		mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+		if (!mux)
+			return ERR_PTR(-ENOMEM);
+
+		mux->reg = base + mc->mux_reg;
+		mux->mask = BIT(mc->mux_width) - 1;
+		mux->shift = mc->mux_shift;
+		mux->lock = lock;
+
+		mux_hw = &mux->hw;
+		mux_ops = &clk_mux_ops;
+
+		parent_names = mc->parent_names;
+		num_parents = mc->num_parents;
+	} else {
+		parent = mc->parent;
+		parent_names = &parent;
+		num_parents = 1;
+	}
+
+	if (mc->gate_shift >= 0) {
+		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+		if (!gate) {
+			ret = -ENOMEM;
+			goto err_out;
+		}
+
+		gate->reg = base + mc->gate_reg;
+		gate->bit_idx = mc->gate_shift;
+		gate->flags = CLK_GATE_SET_TO_DISABLE;
+		gate->lock = lock;
+
+		gate_hw = &gate->hw;
+		gate_ops = &clk_gate_ops;
+	}
+
+	if (mc->divider_shift >= 0) {
+		div = kzalloc(sizeof(*div), GFP_KERNEL);
+		if (!div) {
+			ret = -ENOMEM;
+			goto err_out;
+		}
+
+		div->reg = base + mc->divider_reg;
+		div->shift = mc->divider_shift;
+		div->width = mc->divider_width;
+		div->lock = lock;
+
+		div_hw = &div->hw;
+		div_ops = &clk_divider_ops;
+	}
+
+	clk = clk_register_composite(NULL, mc->name, parent_names, num_parents,
+		mux_hw, mux_ops,
+		div_hw, div_ops,
+		gate_hw, gate_ops,
+		mc->flags);
+
+	if (IS_ERR(clk)) {
+		kfree(gate);
+		kfree(mux);
+	}
+
+	return clk;
+err_out:
+	kfree(mux);
+
+	return ERR_PTR(ret);
+}
+
+void mtk_clk_register_composites(const struct mtk_composite *mcs,
+		int num, void __iomem *base, spinlock_t *lock,
+		struct clk_onecell_data *clk_data)
+{
+	struct clk *clk;
+	int i;
+
+	for (i = 0; i < num; i++) {
+		const struct mtk_composite *mc = &mcs[i];
+
+		clk = mtk_clk_register_composite(mc, base, lock);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					mc->name, PTR_ERR(clk));
+			continue;
+		}
+
+		if (clk_data)
+			clk_data->clks[mc->id] = clk;
+	}
+}
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
new file mode 100644
index 000000000000..38f8ceb0470b
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DRV_CLK_MTK_H
+#define __DRV_CLK_MTK_H
+
+#include <linux/regmap.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#define MAX_MUX_GATE_BIT	31
+#define INVALID_MUX_GATE_BIT	(MAX_MUX_GATE_BIT + 1)
+
+#define MHZ (1000 * 1000)
+
+struct mtk_fixed_factor {
+	int id;
+	const char *name;
+	const char *parent_name;
+	int mult;
+	int div;
+};
+
+#define FACTOR(_id, _name, _parent, _mult, _div) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.mult = _mult,				\
+		.div = _div,				\
+	}
+
+extern void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
+		int num, struct clk_onecell_data *clk_data);
+
+struct mtk_composite {
+	int id;
+	const char *name;
+	const char * const *parent_names;
+	const char *parent;
+	unsigned flags;
+
+	uint32_t mux_reg;
+	uint32_t divider_reg;
+	uint32_t gate_reg;
+
+	signed char mux_shift;
+	signed char mux_width;
+	signed char gate_shift;
+
+	signed char divider_shift;
+	signed char divider_width;
+
+	signed char num_parents;
+};
+
+#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) {	\
+		.id = _id,						\
+		.name = _name,						\
+		.mux_reg = _reg,					\
+		.mux_shift = _shift,					\
+		.mux_width = _width,					\
+		.gate_reg = _reg,					\
+		.gate_shift = _gate,					\
+		.divider_shift = -1,					\
+		.parent_names = _parents,				\
+		.num_parents = ARRAY_SIZE(_parents),			\
+		.flags = CLK_SET_RATE_PARENT,				\
+	}
+
+#define MUX(_id, _name, _parents, _reg, _shift, _width) {		\
+		.id = _id,						\
+		.name = _name,						\
+		.mux_reg = _reg,					\
+		.mux_shift = _shift,					\
+		.mux_width = _width,					\
+		.gate_shift = -1,					\
+		.divider_shift = -1,					\
+		.parent_names = _parents,				\
+		.num_parents = ARRAY_SIZE(_parents),			\
+		.flags = CLK_SET_RATE_PARENT,				\
+	}
+
+#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) {	\
+		.id = _id,						\
+		.parent = _parent,					\
+		.name = _name,						\
+		.divider_reg = _div_reg,				\
+		.divider_shift = _div_shift,				\
+		.divider_width = _div_width,				\
+		.gate_reg = _gate_reg,					\
+		.gate_shift = _gate_shift,				\
+		.mux_shift = -1,					\
+		.flags = 0,						\
+	}
+
+struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
+		void __iomem *base, spinlock_t *lock);
+
+void mtk_clk_register_composites(const struct mtk_composite *mcs,
+		int num, void __iomem *base, spinlock_t *lock,
+		struct clk_onecell_data *clk_data);
+
+struct mtk_gate_regs {
+	u32 sta_ofs;
+	u32 clr_ofs;
+	u32 set_ofs;
+};
+
+struct mtk_gate {
+	int id;
+	const char *name;
+	const char *parent_name;
+	const struct mtk_gate_regs *regs;
+	int shift;
+	const struct clk_ops *ops;
+};
+
+int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
+		int num, struct clk_onecell_data *clk_data);
+
+struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
+
+#define HAVE_RST_BAR	BIT(0)
+
+struct mtk_pll_data {
+	int id;
+	const char *name;
+	uint32_t reg;
+	uint32_t pwr_reg;
+	uint32_t en_mask;
+	uint32_t pd_reg;
+	uint32_t tuner_reg;
+	int pd_shift;
+	unsigned int flags;
+	const struct clk_ops *ops;
+	u32 rst_bar_mask;
+	unsigned long fmax;
+	int pcwbits;
+	uint32_t pcw_reg;
+	int pcw_shift;
+};
+
+void __init mtk_clk_register_plls(struct device_node *node,
+		const struct mtk_pll_data *plls, int num_plls,
+		struct clk_onecell_data *clk_data);
+
+#endif /* __DRV_CLK_MTK_H */
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
new file mode 100644
index 000000000000..66154caf992a
--- /dev/null
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+
+#include "clk-mtk.h"
+
+#define REG_CON0		0
+#define REG_CON1		4
+
+#define CON0_BASE_EN		BIT(0)
+#define CON0_PWR_ON		BIT(0)
+#define CON0_ISO_EN		BIT(1)
+#define CON0_PCW_CHG		BIT(31)
+
+#define AUDPLL_TUNER_EN		BIT(31)
+
+#define POSTDIV_MASK		0x7
+#define INTEGER_BITS		7
+
+/*
+ * MediaTek PLLs are configured through their pcw value. The pcw value describes
+ * a divider in the PLL feedback loop which consists of 7 bits for the integer
+ * part and the remaining bits (if present) for the fractional part. Also they
+ * have a 3 bit power-of-two post divider.
+ */
+
+struct mtk_clk_pll {
+	struct clk_hw	hw;
+	void __iomem	*base_addr;
+	void __iomem	*pd_addr;
+	void __iomem	*pwr_addr;
+	void __iomem	*tuner_addr;
+	void __iomem	*pcw_addr;
+	const struct mtk_pll_data *data;
+};
+
+static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw)
+{
+	return container_of(hw, struct mtk_clk_pll, hw);
+}
+
+static int mtk_pll_is_prepared(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+	return (readl(pll->base_addr + REG_CON0) & CON0_BASE_EN) != 0;
+}
+
+static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin,
+		u32 pcw, int postdiv)
+{
+	int pcwbits = pll->data->pcwbits;
+	int pcwfbits;
+	u64 vco;
+	u8 c = 0;
+
+	/* The fractional part of the PLL divider. */
+	pcwfbits = pcwbits > INTEGER_BITS ? pcwbits - INTEGER_BITS : 0;
+
+	vco = (u64)fin * pcw;
+
+	if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0)))
+		c = 1;
+
+	vco >>= pcwfbits;
+
+	if (c)
+		vco++;
+
+	return ((unsigned long)vco + postdiv - 1) / postdiv;
+}
+
+static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
+		int postdiv)
+{
+	u32 con1, pd, val;
+	int pll_en;
+
+	/* set postdiv */
+	pd = readl(pll->pd_addr);
+	pd &= ~(POSTDIV_MASK << pll->data->pd_shift);
+	pd |= (ffs(postdiv) - 1) << pll->data->pd_shift;
+	writel(pd, pll->pd_addr);
+
+	pll_en = readl(pll->base_addr + REG_CON0) & CON0_BASE_EN;
+
+	/* set pcw */
+	val = readl(pll->pcw_addr);
+
+	val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1,
+			pll->data->pcw_shift);
+	val |= pcw << pll->data->pcw_shift;
+	writel(val, pll->pcw_addr);
+
+	con1 = readl(pll->base_addr + REG_CON1);
+
+	if (pll_en)
+		con1 |= CON0_PCW_CHG;
+
+	writel(con1, pll->base_addr + REG_CON1);
+	if (pll->tuner_addr)
+		writel(con1 + 1, pll->tuner_addr);
+
+	if (pll_en)
+		udelay(20);
+}
+
+/*
+ * mtk_pll_calc_values - calculate good values for a given input frequency.
+ * @pll:	The pll
+ * @pcw:	The pcw value (output)
+ * @postdiv:	The post divider (output)
+ * @freq:	The desired target frequency
+ * @fin:	The input frequency
+ *
+ */
+static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
+		u32 freq, u32 fin)
+{
+	unsigned long fmin = 1000 * MHZ;
+	u64 _pcw;
+	u32 val;
+
+	if (freq > pll->data->fmax)
+		freq = pll->data->fmax;
+
+	for (val = 0; val < 4; val++) {
+		*postdiv = 1 << val;
+		if (freq * *postdiv >= fmin)
+			break;
+	}
+
+	/* _pcw = freq * postdiv / fin * 2^pcwfbits */
+	_pcw = ((u64)freq << val) << (pll->data->pcwbits - INTEGER_BITS);
+	do_div(_pcw, fin);
+
+	*pcw = (u32)_pcw;
+}
+
+static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 pcw = 0;
+	u32 postdiv;
+
+	mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate);
+	mtk_pll_set_rate_regs(pll, pcw, postdiv);
+
+	return 0;
+}
+
+static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 postdiv;
+	u32 pcw;
+
+	postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & POSTDIV_MASK;
+	postdiv = 1 << postdiv;
+
+	pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift;
+	pcw &= GENMASK(pll->data->pcwbits - 1, 0);
+
+	return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv);
+}
+
+static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *prate)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 pcw = 0;
+	int postdiv;
+
+	mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate);
+
+	return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv);
+}
+
+static int mtk_pll_prepare(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 r;
+
+	r = readl(pll->pwr_addr) | CON0_PWR_ON;
+	writel(r, pll->pwr_addr);
+	udelay(1);
+
+	r = readl(pll->pwr_addr) & ~CON0_ISO_EN;
+	writel(r, pll->pwr_addr);
+	udelay(1);
+
+	r = readl(pll->base_addr + REG_CON0);
+	r |= pll->data->en_mask;
+	writel(r, pll->base_addr + REG_CON0);
+
+	if (pll->tuner_addr) {
+		r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
+		writel(r, pll->tuner_addr);
+	}
+
+	udelay(20);
+
+	if (pll->data->flags & HAVE_RST_BAR) {
+		r = readl(pll->base_addr + REG_CON0);
+		r |= pll->data->rst_bar_mask;
+		writel(r, pll->base_addr + REG_CON0);
+	}
+
+	return 0;
+}
+
+static void mtk_pll_unprepare(struct clk_hw *hw)
+{
+	struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+	u32 r;
+
+	if (pll->data->flags & HAVE_RST_BAR) {
+		r = readl(pll->base_addr + REG_CON0);
+		r &= ~pll->data->rst_bar_mask;
+		writel(r, pll->base_addr + REG_CON0);
+	}
+
+	if (pll->tuner_addr) {
+		r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
+		writel(r, pll->tuner_addr);
+	}
+
+	r = readl(pll->base_addr + REG_CON0);
+	r &= ~CON0_BASE_EN;
+	writel(r, pll->base_addr + REG_CON0);
+
+	r = readl(pll->pwr_addr) | CON0_ISO_EN;
+	writel(r, pll->pwr_addr);
+
+	r = readl(pll->pwr_addr) & ~CON0_PWR_ON;
+	writel(r, pll->pwr_addr);
+}
+
+static const struct clk_ops mtk_pll_ops = {
+	.is_prepared	= mtk_pll_is_prepared,
+	.prepare	= mtk_pll_prepare,
+	.unprepare	= mtk_pll_unprepare,
+	.recalc_rate	= mtk_pll_recalc_rate,
+	.round_rate	= mtk_pll_round_rate,
+	.set_rate	= mtk_pll_set_rate,
+};
+
+static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
+		void __iomem *base)
+{
+	struct mtk_clk_pll *pll;
+	struct clk_init_data init;
+	struct clk *clk;
+	const char *parent_name = "clk26m";
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	pll->base_addr = base + data->reg;
+	pll->pwr_addr = base + data->pwr_reg;
+	pll->pd_addr = base + data->pd_reg;
+	pll->pcw_addr = base + data->pcw_reg;
+	if (data->tuner_reg)
+		pll->tuner_addr = base + data->tuner_reg;
+	pll->hw.init = &init;
+	pll->data = data;
+
+	init.name = data->name;
+	init.ops = &mtk_pll_ops;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	clk = clk_register(NULL, &pll->hw);
+
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+void __init mtk_clk_register_plls(struct device_node *node,
+		const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
+{
+	void __iomem *base;
+	int r, i;
+	struct clk *clk;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	for (i = 0; i < num_plls; i++) {
+		const struct mtk_pll_data *pll = &plls[i];
+
+		clk = mtk_clk_register_pll(pll, base);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+					pll->name, PTR_ERR(clk));
+			continue;
+		}
+
+		clk_data->clks[pll->id] = clk;
+	}
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}

From d633fb7ac1e6abc39270edebbfa23131c673b5b9 Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer@pengutronix.de>
Date: Thu, 23 Apr 2015 10:35:40 +0200
Subject: [PATCH 012/135] clk: mediatek: Add reset controller support

The pericfg and infracfg units also provide reset lines to several
other SoC internal units. This adds a function which can be called
from the pericfg and infracfg initialization functions which will
register the reset controller using reset_controller_register. The
reset controller will provide support for resetting the units
connected to the pericfg and infracfg controller. The units resetted
by this controller can use the standard reset device tree binding
to gain access to the reset lines.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/mediatek/Makefile  |  1 +
 drivers/clk/mediatek/clk-mtk.h | 10 ++++
 drivers/clk/mediatek/reset.c   | 97 ++++++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)
 create mode 100644 drivers/clk/mediatek/reset.c

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index c384e9778d1a..0b6f1c3c9c69 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1 +1,2 @@
 obj-y += clk-mtk.o clk-pll.o clk-gate.o
+obj-$(CONFIG_RESET_CONTROLLER) += reset.o
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index 38f8ceb0470b..9dda9d8ad10b 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -156,4 +156,14 @@ void __init mtk_clk_register_plls(struct device_node *node,
 		const struct mtk_pll_data *plls, int num_plls,
 		struct clk_onecell_data *clk_data);
 
+#ifdef CONFIG_RESET_CONTROLLER
+void mtk_register_reset_controller(struct device_node *np,
+			unsigned int num_regs, int regofs);
+#else
+static inline void mtk_register_reset_controller(struct device_node *np,
+			unsigned int num_regs, int regofs)
+{
+}
+#endif
+
 #endif /* __DRV_CLK_MTK_H */
diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c
new file mode 100644
index 000000000000..9e9fe4b19ac4
--- /dev/null
+++ b/drivers/clk/mediatek/reset.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+
+#include "clk-mtk.h"
+
+struct mtk_reset {
+	struct regmap *regmap;
+	int regofs;
+	struct reset_controller_dev rcdev;
+};
+
+static int mtk_reset_assert(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
+
+	return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
+			BIT(id % 32), ~0);
+}
+
+static int mtk_reset_deassert(struct reset_controller_dev *rcdev,
+				unsigned long id)
+{
+	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
+
+	return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2),
+			BIT(id % 32), 0);
+}
+
+static int mtk_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	int ret;
+
+	ret = mtk_reset_assert(rcdev, id);
+	if (ret)
+		return ret;
+
+	return mtk_reset_deassert(rcdev, id);
+}
+
+static struct reset_control_ops mtk_reset_ops = {
+	.assert = mtk_reset_assert,
+	.deassert = mtk_reset_deassert,
+	.reset = mtk_reset,
+};
+
+void mtk_register_reset_controller(struct device_node *np,
+			unsigned int num_regs, int regofs)
+{
+	struct mtk_reset *data;
+	int ret;
+	struct regmap *regmap;
+
+	regmap = syscon_node_to_regmap(np);
+	if (IS_ERR(regmap)) {
+		pr_err("Cannot find regmap for %s: %ld\n", np->full_name,
+				PTR_ERR(regmap));
+		return;
+	}
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return;
+
+	data->regmap = regmap;
+	data->regofs = regofs;
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = num_regs * 32;
+	data->rcdev.ops = &mtk_reset_ops;
+	data->rcdev.of_node = np;
+
+	ret = reset_controller_register(&data->rcdev);
+	if (ret) {
+		pr_err("could not register reset controller: %d\n", ret);
+		kfree(data);
+		return;
+	}
+}

From a8aede7948438f3a9c830a5a865ae6a78c5fc4ca Mon Sep 17 00:00:00 2001
From: James Liao <jamesjj.liao@mediatek.com>
Date: Thu, 23 Apr 2015 10:35:41 +0200
Subject: [PATCH 013/135] clk: mediatek: Add basic clocks for Mediatek MT8135.

This patch adds basic clocks for MT8135, including TOPCKGEN, PLLs,
INFRA and PERI clocks.

Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/mediatek/Makefile                 |   1 +
 drivers/clk/mediatek/clk-mt8135.c             | 644 ++++++++++++++++++
 include/dt-bindings/clock/mt8135-clk.h        | 194 ++++++
 .../reset-controller/mt8135-resets.h          |  64 ++
 4 files changed, 903 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8135.c
 create mode 100644 include/dt-bindings/clock/mt8135-clk.h
 create mode 100644 include/dt-bindings/reset-controller/mt8135-resets.h

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 0b6f1c3c9c69..12ce576e628a 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,2 +1,3 @@
 obj-y += clk-mtk.o clk-pll.o clk-gate.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+obj-y += clk-mt8135.o
diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c
new file mode 100644
index 000000000000..a63435b95822
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8135.c
@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+#include <dt-bindings/clock/mt8135-clk.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+static DEFINE_SPINLOCK(mt8135_clk_lock);
+
+static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
+	FACTOR(CLK_TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1),
+};
+
+static const struct mtk_fixed_factor top_divs[] __initconst = {
+	FACTOR(CLK_TOP_MAINPLL_806M, "mainpll_806m", "mainpll", 1, 2),
+	FACTOR(CLK_TOP_MAINPLL_537P3M, "mainpll_537p3m", "mainpll", 1, 3),
+	FACTOR(CLK_TOP_MAINPLL_322P4M, "mainpll_322p4m", "mainpll", 1, 5),
+	FACTOR(CLK_TOP_MAINPLL_230P3M, "mainpll_230p3m", "mainpll", 1, 7),
+
+	FACTOR(CLK_TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3),
+	FACTOR(CLK_TOP_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5),
+	FACTOR(CLK_TOP_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7),
+	FACTOR(CLK_TOP_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26),
+
+	FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+	FACTOR(CLK_TOP_MMPLL_D3, "mmpll_d3", "mmpll", 1, 3),
+	FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5),
+	FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7),
+	FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll_d2", 1, 2),
+	FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll_d3", 1, 2),
+
+	FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll_806m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL_D4, "syspll_d4", "mainpll_806m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL_D6, "syspll_d6", "mainpll_806m", 1, 3),
+	FACTOR(CLK_TOP_SYSPLL_D8, "syspll_d8", "mainpll_806m", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL_D10, "syspll_d10", "mainpll_806m", 1, 5),
+	FACTOR(CLK_TOP_SYSPLL_D12, "syspll_d12", "mainpll_806m", 1, 6),
+	FACTOR(CLK_TOP_SYSPLL_D16, "syspll_d16", "mainpll_806m", 1, 8),
+	FACTOR(CLK_TOP_SYSPLL_D24, "syspll_d24", "mainpll_806m", 1, 12),
+
+	FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll_537p3m", 1, 1),
+
+	FACTOR(CLK_TOP_SYSPLL_D2P5, "syspll_d2p5", "mainpll_322p4m", 2, 1),
+	FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll_322p4m", 1, 1),
+
+	FACTOR(CLK_TOP_SYSPLL_D3P5, "syspll_d3p5", "mainpll_230p3m", 2, 1),
+
+	FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6),
+	FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10),
+
+	FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6),
+	FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8),
+
+	FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll_416m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll_178p3m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1),
+
+	FACTOR(CLK_TOP_APLL, "apll_ck", "audpll", 1, 1),
+	FACTOR(CLK_TOP_APLL_D4, "apll_d4", "audpll", 1, 4),
+	FACTOR(CLK_TOP_APLL_D8, "apll_d8", "audpll", 1, 8),
+	FACTOR(CLK_TOP_APLL_D16, "apll_d16", "audpll", 1, 16),
+	FACTOR(CLK_TOP_APLL_D24, "apll_d24", "audpll", 1, 24),
+
+	FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
+	FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
+	FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
+
+	FACTOR(CLK_TOP_LVDSTX_CLKDIG_CT, "lvdstx_clkdig_cts", "lvdspll", 1, 1),
+	FACTOR(CLK_TOP_VPLL_DPIX, "vpll_dpix_ck", "lvdspll", 1, 1),
+
+	FACTOR(CLK_TOP_TVHDMI_H, "tvhdmi_h_ck", "tvdpll", 1, 1),
+
+	FACTOR(CLK_TOP_HDMITX_CLKDIG_D2, "hdmitx_clkdig_d2", "hdmitx_clkdig_cts", 1, 2),
+	FACTOR(CLK_TOP_HDMITX_CLKDIG_D3, "hdmitx_clkdig_d3", "hdmitx_clkdig_cts", 1, 3),
+
+	FACTOR(CLK_TOP_TVHDMI_D2, "tvhdmi_d2", "tvhdmi_h_ck", 1, 2),
+	FACTOR(CLK_TOP_TVHDMI_D4, "tvhdmi_d4", "tvhdmi_h_ck", 1, 4),
+
+	FACTOR(CLK_TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4),
+};
+
+static const char * const axi_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3",
+	"syspll_d4",
+	"syspll_d6",
+	"univpll_d5",
+	"univpll2_d2",
+	"syspll_d3p5"
+};
+
+static const char * const smi_parents[] __initconst = {
+	"clk26m",
+	"clkph_mck",
+	"syspll_d2p5",
+	"syspll_d3",
+	"syspll_d8",
+	"univpll_d5",
+	"univpll1_d2",
+	"univpll1_d6",
+	"mmpll_d3",
+	"mmpll_d4",
+	"mmpll_d5",
+	"mmpll_d6",
+	"mmpll_d7",
+	"vdecpll",
+	"lvdspll"
+};
+
+static const char * const mfg_parents[] __initconst = {
+	"clk26m",
+	"univpll1_d4",
+	"syspll_d2",
+	"syspll_d2p5",
+	"syspll_d3",
+	"univpll_d5",
+	"univpll1_d2",
+	"mmpll_d2",
+	"mmpll_d3",
+	"mmpll_d4",
+	"mmpll_d5",
+	"mmpll_d6",
+	"mmpll_d7"
+};
+
+static const char * const irda_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8",
+	"univpll1_d6"
+};
+
+static const char * const cam_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3",
+	"syspll_d3p5",
+	"syspll_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"univpll_d7",
+	"univpll1_d4"
+};
+
+static const char * const aud_intbus_parents[] __initconst = {
+	"clk26m",
+	"syspll_d6",
+	"univpll_d10"
+};
+
+static const char * const jpg_parents[] __initconst = {
+	"clk26m",
+	"syspll_d5",
+	"syspll_d4",
+	"syspll_d3",
+	"univpll_d7",
+	"univpll2_d2",
+	"univpll_d5"
+};
+
+static const char * const disp_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3p5",
+	"syspll_d3",
+	"univpll2_d2",
+	"univpll_d5",
+	"univpll1_d2",
+	"lvdspll",
+	"vdecpll"
+};
+
+static const char * const msdc30_parents[] __initconst = {
+	"clk26m",
+	"syspll_d6",
+	"syspll_d5",
+	"univpll1_d4",
+	"univpll2_d4",
+	"msdcpll"
+};
+
+static const char * const usb20_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d6",
+	"univpll1_d10"
+};
+
+static const char * const venc_parents[] __initconst = {
+	"clk26m",
+	"syspll_d3",
+	"syspll_d8",
+	"univpll_d5",
+	"univpll1_d6",
+	"mmpll_d4",
+	"mmpll_d5",
+	"mmpll_d6"
+};
+
+static const char * const spi_parents[] __initconst = {
+	"clk26m",
+	"syspll_d6",
+	"syspll_d8",
+	"syspll_d10",
+	"univpll1_d6",
+	"univpll1_d8"
+};
+
+static const char * const uart_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8"
+};
+
+static const char * const mem_parents[] __initconst = {
+	"clk26m",
+	"clkph_mck"
+};
+
+static const char * const camtg_parents[] __initconst = {
+	"clk26m",
+	"univpll_d26",
+	"univpll1_d6",
+	"syspll_d16",
+	"syspll_d8"
+};
+
+static const char * const audio_parents[] __initconst = {
+	"clk26m",
+	"syspll_d24"
+};
+
+static const char * const fix_parents[] __initconst = {
+	"rtc32k",
+	"clk26m",
+	"univpll_d5",
+	"univpll_d7",
+	"univpll1_d2",
+	"univpll1_d4",
+	"univpll1_d6",
+	"univpll1_d8"
+};
+
+static const char * const vdec_parents[] __initconst = {
+	"clk26m",
+	"vdecpll",
+	"clkph_mck",
+	"syspll_d2p5",
+	"syspll_d3",
+	"syspll_d3p5",
+	"syspll_d4",
+	"syspll_d5",
+	"syspll_d6",
+	"syspll_d8",
+	"univpll1_d2",
+	"univpll2_d2",
+	"univpll_d7",
+	"univpll_d10",
+	"univpll2_d4",
+	"lvdspll"
+};
+
+static const char * const ddrphycfg_parents[] __initconst = {
+	"clk26m",
+	"axi_sel",
+	"syspll_d12"
+};
+
+static const char * const dpilvds_parents[] __initconst = {
+	"clk26m",
+	"lvdspll",
+	"lvdspll_d2",
+	"lvdspll_d4",
+	"lvdspll_d8"
+};
+
+static const char * const pmicspi_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d6",
+	"syspll_d8",
+	"syspll_d10",
+	"univpll1_d10",
+	"mempll_mck_d4",
+	"univpll_d26",
+	"syspll_d24"
+};
+
+static const char * const smi_mfg_as_parents[] __initconst = {
+	"clk26m",
+	"smi_sel",
+	"mfg_sel",
+	"mem_sel"
+};
+
+static const char * const gcpu_parents[] __initconst = {
+	"clk26m",
+	"syspll_d4",
+	"univpll_d7",
+	"syspll_d5",
+	"syspll_d6"
+};
+
+static const char * const dpi1_parents[] __initconst = {
+	"clk26m",
+	"tvhdmi_h_ck",
+	"tvhdmi_d2",
+	"tvhdmi_d4"
+};
+
+static const char * const cci_parents[] __initconst = {
+	"clk26m",
+	"mainpll_537p3m",
+	"univpll_d3",
+	"syspll_d2p5",
+	"syspll_d3",
+	"syspll_d5"
+};
+
+static const char * const apll_parents[] __initconst = {
+	"clk26m",
+	"apll_ck",
+	"apll_d4",
+	"apll_d8",
+	"apll_d16",
+	"apll_d24"
+};
+
+static const char * const hdmipll_parents[] __initconst = {
+	"clk26m",
+	"hdmitx_clkdig_cts",
+	"hdmitx_clkdig_d2",
+	"hdmitx_clkdig_d3"
+};
+
+static const struct mtk_composite top_muxes[] __initconst = {
+	/* CLK_CFG_0 */
+	MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
+		0x0140, 0, 3, INVALID_MUX_GATE_BIT),
+	MUX_GATE(CLK_TOP_SMI_SEL, "smi_sel", smi_parents, 0x0140, 8, 4, 15),
+	MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0140, 16, 4, 23),
+	MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x0140, 24, 2, 31),
+	/* CLK_CFG_1 */
+	MUX_GATE(CLK_TOP_CAM_SEL, "cam_sel", cam_parents, 0x0144, 0, 3, 7),
+	MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
+		0x0144, 8, 2, 15),
+	MUX_GATE(CLK_TOP_JPG_SEL, "jpg_sel", jpg_parents, 0x0144, 16, 3, 23),
+	MUX_GATE(CLK_TOP_DISP_SEL, "disp_sel", disp_parents, 0x0144, 24, 3, 31),
+	/* CLK_CFG_2 */
+	MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents, 0x0148, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents, 0x0148, 8, 3, 15),
+	MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents, 0x0148, 16, 3, 23),
+	MUX_GATE(CLK_TOP_MSDC30_4_SEL, "msdc30_4_sel", msdc30_parents, 0x0148, 24, 3, 31),
+	/* CLK_CFG_3 */
+	MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x014c, 0, 2, 7),
+	/* CLK_CFG_4 */
+	MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0150, 8, 3, 15),
+	MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0150, 16, 3, 23),
+	MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0150, 24, 2, 31),
+	/* CLK_CFG_6 */
+	MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0158, 0, 2, 7),
+	MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0158, 8, 3, 15),
+	MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0158, 24, 2, 31),
+	/* CLK_CFG_7 */
+	MUX_GATE(CLK_TOP_FIX_SEL, "fix_sel", fix_parents, 0x015c, 0, 3, 7),
+	MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x015c, 8, 4, 15),
+	MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents,
+		0x015c, 16, 2, 23),
+	MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x015c, 24, 3, 31),
+	/* CLK_CFG_8 */
+	MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0164, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents, 0x0164, 8, 3, 15),
+	MUX_GATE(CLK_TOP_SMI_MFG_AS_SEL, "smi_mfg_as_sel", smi_mfg_as_parents,
+		0x0164, 16, 2, 23),
+	MUX_GATE(CLK_TOP_GCPU_SEL, "gcpu_sel", gcpu_parents, 0x0164, 24, 3, 31),
+	/* CLK_CFG_9 */
+	MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0168, 0, 2, 7),
+	MUX_GATE(CLK_TOP_CCI_SEL, "cci_sel", cci_parents, 0x0168, 8, 3, 15),
+	MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents, 0x0168, 16, 3, 23),
+	MUX_GATE(CLK_TOP_HDMIPLL_SEL, "hdmipll_sel", hdmipll_parents, 0x0168, 24, 2, 31),
+};
+
+static const struct mtk_gate_regs infra_cg_regs = {
+	.set_ofs = 0x0040,
+	.clr_ofs = 0x0044,
+	.sta_ofs = 0x0048,
+};
+
+#define GATE_ICG(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &infra_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+static const struct mtk_gate infra_clks[] __initconst = {
+	GATE_ICG(CLK_INFRA_PMIC_WRAP, "pmic_wrap_ck", "axi_sel", 23),
+	GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
+	GATE_ICG(CLK_INFRA_CCIF1_AP_CTRL, "ccif1_ap_ctrl", "axi_sel", 21),
+	GATE_ICG(CLK_INFRA_CCIF0_AP_CTRL, "ccif0_ap_ctrl", "axi_sel", 20),
+	GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
+	GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "cpum_tck_in", 15),
+	GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
+	GATE_ICG(CLK_INFRA_MFGAXI, "mfgaxi_ck", "axi_sel", 7),
+	GATE_ICG(CLK_INFRA_DEVAPC, "devapc_ck", "axi_sel", 6),
+	GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "aud_intbus_sel", 5),
+	GATE_ICG(CLK_INFRA_MFG_BUS, "mfg_bus_ck", "axi_sel", 2),
+	GATE_ICG(CLK_INFRA_SMI, "smi_ck", "smi_sel", 1),
+	GATE_ICG(CLK_INFRA_DBGCLK, "dbgclk_ck", "axi_sel", 0),
+};
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x0010,
+	.sta_ofs = 0x0018,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+	.set_ofs = 0x000c,
+	.clr_ofs = 0x0014,
+	.sta_ofs = 0x001c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &peri0_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+#define GATE_PERI1(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &peri1_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+static const struct mtk_gate peri_gates[] __initconst = {
+	/* PERI0 */
+	GATE_PERI0(CLK_PERI_I2C5, "i2c5_ck", "axi_sel", 31),
+	GATE_PERI0(CLK_PERI_I2C4, "i2c4_ck", "axi_sel", 30),
+	GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "axi_sel", 29),
+	GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 28),
+	GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 27),
+	GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 26),
+	GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 25),
+	GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 24),
+	GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 23),
+	GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 22),
+	GATE_PERI0(CLK_PERI_IRDA, "irda_ck", "irda_sel", 21),
+	GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 20),
+	GATE_PERI0(CLK_PERI_MD_HIF, "md_hif_ck", "axi_sel", 19),
+	GATE_PERI0(CLK_PERI_AP_HIF, "ap_hif_ck", "axi_sel", 18),
+	GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_4_sel", 17),
+	GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_3_sel", 16),
+	GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_2_sel", 15),
+	GATE_PERI0(CLK_PERI_MSDC20_2, "msdc20_2_ck", "msdc30_1_sel", 14),
+	GATE_PERI0(CLK_PERI_MSDC20_1, "msdc20_1_ck", "msdc30_0_sel", 13),
+	GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
+	GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
+	GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
+	GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
+	GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
+	GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
+	GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
+	GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
+	GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
+	GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
+	GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
+	GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
+	GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "axi_sel", 0),
+	/* PERI1 */
+	GATE_PERI1(CLK_PERI_USBSLV, "usbslv_ck", "axi_sel", 8),
+	GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 7),
+	GATE_PERI1(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 6),
+	GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "gcpu_sel", 5),
+	GATE_PERI1(CLK_PERI_FHCTL, "fhctl_ck", "clk26m", 4),
+	GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi_sel", 3),
+	GATE_PERI1(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 2),
+	GATE_PERI1(CLK_PERI_PERI_PWRAP, "peri_pwrap_ck", "axi_sel", 1),
+	GATE_PERI1(CLK_PERI_I2C6, "i2c6_ck", "axi_sel", 0),
+};
+
+static const char * const uart_ck_sel_parents[] __initconst = {
+	"clk26m",
+	"uart_sel",
+};
+
+static const struct mtk_composite peri_clks[] __initconst = {
+	MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
+	MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
+	MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
+	MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
+};
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	int r;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+	mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
+	mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+	mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
+			&mt8135_clk_lock, clk_data);
+
+	clk_prepare_enable(clk_data->clks[CLK_TOP_CCI_SEL]);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8135-topckgen", mtk_topckgen_init);
+
+static void __init mtk_infrasys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+
+	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+						clk_data);
+
+	clk_prepare_enable(clk_data->clks[CLK_INFRA_M4U]);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0x30);
+}
+CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8135-infracfg", mtk_infrasys_init);
+
+static void __init mtk_pericfg_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	void __iomem *base;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+
+	mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
+						clk_data);
+	mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
+			&mt8135_clk_lock, clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0);
+}
+CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8135-pericfg", mtk_pericfg_init);
+
+#define MT8135_PLL_FMAX		(2000 * MHZ)
+#define CON0_MT8135_RST_BAR	BIT(27)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \
+		.id = _id,						\
+		.name = _name,						\
+		.reg = _reg,						\
+		.pwr_reg = _pwr_reg,					\
+		.en_mask = _en_mask,					\
+		.flags = _flags,					\
+		.rst_bar_mask = CON0_MT8135_RST_BAR,			\
+		.fmax = MT8135_PLL_FMAX,				\
+		.pcwbits = _pcwbits,					\
+		.pd_reg = _pd_reg,					\
+		.pd_shift = _pd_shift,					\
+		.tuner_reg = _tuner_reg,				\
+		.pcw_reg = _pcw_reg,					\
+		.pcw_shift = _pcw_shift,				\
+	}
+
+static const struct mtk_pll_data plls[] = {
+	PLL(CLK_APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
+	PLL(CLK_APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000001, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0),
+	PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000001, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0),
+	PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000001, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9),
+	PLL(CLK_APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000001, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0),
+	PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000001, 0, 21, 0x278, 6, 0x0, 0x27c, 0),
+	PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000001, 0, 31, 0x294, 6, 0x0, 0x298, 0),
+	PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2b0, 0x2c8,	0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0),
+	PLL(CLK_APMIXED_AUDPLL, "audpll", 0x2e8, 0x300, 0x80000001, 0, 31, 0x2e8, 6, 0x2f8, 0x2ec, 0),
+	PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x304, 0x31c,	0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x308, 0),
+};
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+
+	clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
+	if (!clk_data)
+		return;
+
+	mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8135-apmixedsys",
+		mtk_apmixedsys_init);
diff --git a/include/dt-bindings/clock/mt8135-clk.h b/include/dt-bindings/clock/mt8135-clk.h
new file mode 100644
index 000000000000..6dac6c091dd2
--- /dev/null
+++ b/include/dt-bindings/clock/mt8135-clk.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT8135_H
+#define _DT_BINDINGS_CLK_MT8135_H
+
+/* TOPCKGEN */
+
+#define CLK_TOP_DSI0_LNTC_DSICLK	1
+#define CLK_TOP_HDMITX_CLKDIG_CTS	2
+#define CLK_TOP_CLKPH_MCK		3
+#define CLK_TOP_CPUM_TCK_IN		4
+#define CLK_TOP_MAINPLL_806M		5
+#define CLK_TOP_MAINPLL_537P3M		6
+#define CLK_TOP_MAINPLL_322P4M		7
+#define CLK_TOP_MAINPLL_230P3M		8
+#define CLK_TOP_UNIVPLL_624M		9
+#define CLK_TOP_UNIVPLL_416M		10
+#define CLK_TOP_UNIVPLL_249P6M		11
+#define CLK_TOP_UNIVPLL_178P3M		12
+#define CLK_TOP_UNIVPLL_48M		13
+#define CLK_TOP_MMPLL_D2		14
+#define CLK_TOP_MMPLL_D3		15
+#define CLK_TOP_MMPLL_D5		16
+#define CLK_TOP_MMPLL_D7		17
+#define CLK_TOP_MMPLL_D4		18
+#define CLK_TOP_MMPLL_D6		19
+#define CLK_TOP_SYSPLL_D2		20
+#define CLK_TOP_SYSPLL_D4		21
+#define CLK_TOP_SYSPLL_D6		22
+#define CLK_TOP_SYSPLL_D8		23
+#define CLK_TOP_SYSPLL_D10		24
+#define CLK_TOP_SYSPLL_D12		25
+#define CLK_TOP_SYSPLL_D16		26
+#define CLK_TOP_SYSPLL_D24		27
+#define CLK_TOP_SYSPLL_D3		28
+#define CLK_TOP_SYSPLL_D2P5		29
+#define CLK_TOP_SYSPLL_D5		30
+#define CLK_TOP_SYSPLL_D3P5		31
+#define CLK_TOP_UNIVPLL1_D2		32
+#define CLK_TOP_UNIVPLL1_D4		33
+#define CLK_TOP_UNIVPLL1_D6		34
+#define CLK_TOP_UNIVPLL1_D8		35
+#define CLK_TOP_UNIVPLL1_D10		36
+#define CLK_TOP_UNIVPLL2_D2		37
+#define CLK_TOP_UNIVPLL2_D4		38
+#define CLK_TOP_UNIVPLL2_D6		39
+#define CLK_TOP_UNIVPLL2_D8		40
+#define CLK_TOP_UNIVPLL_D3		41
+#define CLK_TOP_UNIVPLL_D5		42
+#define CLK_TOP_UNIVPLL_D7		43
+#define CLK_TOP_UNIVPLL_D10		44
+#define CLK_TOP_UNIVPLL_D26		45
+#define CLK_TOP_APLL			46
+#define CLK_TOP_APLL_D4			47
+#define CLK_TOP_APLL_D8			48
+#define CLK_TOP_APLL_D16		49
+#define CLK_TOP_APLL_D24		50
+#define CLK_TOP_LVDSPLL_D2		51
+#define CLK_TOP_LVDSPLL_D4		52
+#define CLK_TOP_LVDSPLL_D8		53
+#define CLK_TOP_LVDSTX_CLKDIG_CT	54
+#define CLK_TOP_VPLL_DPIX		55
+#define CLK_TOP_TVHDMI_H		56
+#define CLK_TOP_HDMITX_CLKDIG_D2	57
+#define CLK_TOP_HDMITX_CLKDIG_D3	58
+#define CLK_TOP_TVHDMI_D2		59
+#define CLK_TOP_TVHDMI_D4		60
+#define CLK_TOP_MEMPLL_MCK_D4		61
+#define CLK_TOP_AXI_SEL			62
+#define CLK_TOP_SMI_SEL			63
+#define CLK_TOP_MFG_SEL			64
+#define CLK_TOP_IRDA_SEL		65
+#define CLK_TOP_CAM_SEL			66
+#define CLK_TOP_AUD_INTBUS_SEL		67
+#define CLK_TOP_JPG_SEL			68
+#define CLK_TOP_DISP_SEL		69
+#define CLK_TOP_MSDC30_1_SEL		70
+#define CLK_TOP_MSDC30_2_SEL		71
+#define CLK_TOP_MSDC30_3_SEL		72
+#define CLK_TOP_MSDC30_4_SEL		73
+#define CLK_TOP_USB20_SEL		74
+#define CLK_TOP_VENC_SEL		75
+#define CLK_TOP_SPI_SEL			76
+#define CLK_TOP_UART_SEL		77
+#define CLK_TOP_MEM_SEL			78
+#define CLK_TOP_CAMTG_SEL		79
+#define CLK_TOP_AUDIO_SEL		80
+#define CLK_TOP_FIX_SEL			81
+#define CLK_TOP_VDEC_SEL		82
+#define CLK_TOP_DDRPHYCFG_SEL		83
+#define CLK_TOP_DPILVDS_SEL		84
+#define CLK_TOP_PMICSPI_SEL		85
+#define CLK_TOP_MSDC30_0_SEL		86
+#define CLK_TOP_SMI_MFG_AS_SEL		87
+#define CLK_TOP_GCPU_SEL		88
+#define CLK_TOP_DPI1_SEL		89
+#define CLK_TOP_CCI_SEL			90
+#define CLK_TOP_APLL_SEL		91
+#define CLK_TOP_HDMIPLL_SEL		92
+#define CLK_TOP_NR_CLK			93
+
+/* APMIXED_SYS */
+
+#define CLK_APMIXED_ARMPLL1		1
+#define CLK_APMIXED_ARMPLL2		2
+#define CLK_APMIXED_MAINPLL		3
+#define CLK_APMIXED_UNIVPLL		4
+#define CLK_APMIXED_MMPLL		5
+#define CLK_APMIXED_MSDCPLL		6
+#define CLK_APMIXED_TVDPLL		7
+#define CLK_APMIXED_LVDSPLL		8
+#define CLK_APMIXED_AUDPLL		9
+#define CLK_APMIXED_VDECPLL		10
+#define CLK_APMIXED_NR_CLK		11
+
+/* INFRA_SYS */
+
+#define CLK_INFRA_PMIC_WRAP		1
+#define CLK_INFRA_PMICSPI		2
+#define CLK_INFRA_CCIF1_AP_CTRL		3
+#define CLK_INFRA_CCIF0_AP_CTRL		4
+#define CLK_INFRA_KP			5
+#define CLK_INFRA_CPUM			6
+#define CLK_INFRA_M4U			7
+#define CLK_INFRA_MFGAXI		8
+#define CLK_INFRA_DEVAPC		9
+#define CLK_INFRA_AUDIO			10
+#define CLK_INFRA_MFG_BUS		11
+#define CLK_INFRA_SMI			12
+#define CLK_INFRA_DBGCLK		13
+#define CLK_INFRA_NR_CLK		14
+
+/* PERI_SYS */
+
+#define CLK_PERI_I2C5			1
+#define CLK_PERI_I2C4			2
+#define CLK_PERI_I2C3			3
+#define CLK_PERI_I2C2			4
+#define CLK_PERI_I2C1			5
+#define CLK_PERI_I2C0			6
+#define CLK_PERI_UART3			7
+#define CLK_PERI_UART2			8
+#define CLK_PERI_UART1			9
+#define CLK_PERI_UART0			10
+#define CLK_PERI_IRDA			11
+#define CLK_PERI_NLI			12
+#define CLK_PERI_MD_HIF			13
+#define CLK_PERI_AP_HIF			14
+#define CLK_PERI_MSDC30_3		15
+#define CLK_PERI_MSDC30_2		16
+#define CLK_PERI_MSDC30_1		17
+#define CLK_PERI_MSDC20_2		18
+#define CLK_PERI_MSDC20_1		19
+#define CLK_PERI_AP_DMA			20
+#define CLK_PERI_USB1			21
+#define CLK_PERI_USB0			22
+#define CLK_PERI_PWM			23
+#define CLK_PERI_PWM7			24
+#define CLK_PERI_PWM6			25
+#define CLK_PERI_PWM5			26
+#define CLK_PERI_PWM4			27
+#define CLK_PERI_PWM3			28
+#define CLK_PERI_PWM2			29
+#define CLK_PERI_PWM1			30
+#define CLK_PERI_THERM			31
+#define CLK_PERI_NFI			32
+#define CLK_PERI_USBSLV			33
+#define CLK_PERI_USB1_MCU		34
+#define CLK_PERI_USB0_MCU		35
+#define CLK_PERI_GCPU			36
+#define CLK_PERI_FHCTL			37
+#define CLK_PERI_SPI1			38
+#define CLK_PERI_AUXADC			39
+#define CLK_PERI_PERI_PWRAP		40
+#define CLK_PERI_I2C6			41
+#define CLK_PERI_UART0_SEL		42
+#define CLK_PERI_UART1_SEL		43
+#define CLK_PERI_UART2_SEL		44
+#define CLK_PERI_UART3_SEL		45
+#define CLK_PERI_NR_CLK			46
+
+#endif /* _DT_BINDINGS_CLK_MT8135_H */
diff --git a/include/dt-bindings/reset-controller/mt8135-resets.h b/include/dt-bindings/reset-controller/mt8135-resets.h
new file mode 100644
index 000000000000..1fb629508db2
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8135-resets.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8135
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8135
+
+/* INFRACFG resets */
+#define MT8135_INFRA_EMI_REG_RST        0
+#define MT8135_INFRA_DRAMC0_A0_RST      1
+#define MT8135_INFRA_CCIF0_RST          2
+#define MT8135_INFRA_APCIRQ_EINT_RST    3
+#define MT8135_INFRA_APXGPT_RST         4
+#define MT8135_INFRA_SCPSYS_RST         5
+#define MT8135_INFRA_CCIF1_RST          6
+#define MT8135_INFRA_PMIC_WRAP_RST      7
+#define MT8135_INFRA_KP_RST             8
+#define MT8135_INFRA_EMI_RST            32
+#define MT8135_INFRA_DRAMC0_RST         34
+#define MT8135_INFRA_SMI_RST            35
+#define MT8135_INFRA_M4U_RST            36
+
+/*  PERICFG resets */
+#define MT8135_PERI_UART0_SW_RST        0
+#define MT8135_PERI_UART1_SW_RST        1
+#define MT8135_PERI_UART2_SW_RST        2
+#define MT8135_PERI_UART3_SW_RST        3
+#define MT8135_PERI_IRDA_SW_RST         4
+#define MT8135_PERI_PTP_SW_RST          5
+#define MT8135_PERI_AP_HIF_SW_RST       6
+#define MT8135_PERI_GPCU_SW_RST         7
+#define MT8135_PERI_MD_HIF_SW_RST       8
+#define MT8135_PERI_NLI_SW_RST          9
+#define MT8135_PERI_AUXADC_SW_RST       10
+#define MT8135_PERI_DMA_SW_RST          11
+#define MT8135_PERI_NFI_SW_RST          14
+#define MT8135_PERI_PWM_SW_RST          15
+#define MT8135_PERI_THERM_SW_RST        16
+#define MT8135_PERI_MSDC0_SW_RST        17
+#define MT8135_PERI_MSDC1_SW_RST        18
+#define MT8135_PERI_MSDC2_SW_RST        19
+#define MT8135_PERI_MSDC3_SW_RST        20
+#define MT8135_PERI_I2C0_SW_RST         22
+#define MT8135_PERI_I2C1_SW_RST         23
+#define MT8135_PERI_I2C2_SW_RST         24
+#define MT8135_PERI_I2C3_SW_RST         25
+#define MT8135_PERI_I2C4_SW_RST         26
+#define MT8135_PERI_I2C5_SW_RST         27
+#define MT8135_PERI_I2C6_SW_RST         28
+#define MT8135_PERI_USB_SW_RST          29
+#define MT8135_PERI_SPI1_SW_RST         33
+#define MT8135_PERI_PWRAP_BRIDGE_SW_RST 34
+
+#endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT8135 */

From c1e81a3bef36cb046c079480948fa3e0eca590d6 Mon Sep 17 00:00:00 2001
From: James Liao <jamesjj.liao@mediatek.com>
Date: Thu, 23 Apr 2015 10:35:42 +0200
Subject: [PATCH 014/135] clk: mediatek: Add basic clocks for Mediatek MT8173.

This patch adds basic clocks for MT8173, including TOPCKGEN, PLLs,
INFRA and PERI clocks.

Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
Signed-off-by: Henry Chen <henryc.chen@mediatek.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/mediatek/Makefile                 |   1 +
 drivers/clk/mediatek/clk-mt8173.c             | 830 ++++++++++++++++++
 include/dt-bindings/clock/mt8173-clk.h        | 235 +++++
 .../reset-controller/mt8173-resets.h          |  63 ++
 4 files changed, 1129 insertions(+)
 create mode 100644 drivers/clk/mediatek/clk-mt8173.c
 create mode 100644 include/dt-bindings/clock/mt8173-clk.h
 create mode 100644 include/dt-bindings/reset-controller/mt8173-resets.h

diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index 12ce576e628a..8e4b2a4635b9 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,3 +1,4 @@
 obj-y += clk-mtk.o clk-pll.o clk-gate.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
 obj-y += clk-mt8135.o
+obj-y += clk-mt8173.o
diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
new file mode 100644
index 000000000000..357b080eb04f
--- /dev/null
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -0,0 +1,830 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt8173-clk.h>
+
+static DEFINE_SPINLOCK(mt8173_clk_lock);
+
+static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
+	FACTOR(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_DPI, "dpi_ck", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk_null", 1, 1),
+	FACTOR(CLK_TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "clk_null", 1, 1),
+};
+
+static const struct mtk_fixed_factor top_divs[] __initconst = {
+	FACTOR(CLK_TOP_ARMCA7PLL_754M, "armca7pll_754m", "armca7pll", 1, 2),
+	FACTOR(CLK_TOP_ARMCA7PLL_502M, "armca7pll_502m", "armca7pll", 1, 3),
+
+	FACTOR(CLK_TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2),
+	FACTOR(CLK_TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3),
+	FACTOR(CLK_TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5),
+	FACTOR(CLK_TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7),
+
+	FACTOR(CLK_TOP_TVDPLL_445P5M, "tvdpll_445p5m", "tvdpll", 1, 4),
+	FACTOR(CLK_TOP_TVDPLL_594M, "tvdpll_594m", "tvdpll", 1, 3),
+
+	FACTOR(CLK_TOP_UNIV_624M, "univ_624m", "univpll", 1, 2),
+	FACTOR(CLK_TOP_UNIV_416M, "univ_416m", "univpll", 1, 3),
+	FACTOR(CLK_TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5),
+	FACTOR(CLK_TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7),
+	FACTOR(CLK_TOP_UNIV_48M, "univ_48m", "univpll", 1, 26),
+
+	FACTOR(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", "clk32k", 1, 1),
+	FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
+	FACTOR(CLK_TOP_FPC, "fpc_ck", "clk26m", 1, 1),
+
+	FACTOR(CLK_TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2),
+	FACTOR(CLK_TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3),
+
+	FACTOR(CLK_TOP_ARMCA7PLL_D2, "armca7pll_d2", "armca7pll_754m", 1, 1),
+	FACTOR(CLK_TOP_ARMCA7PLL_D3, "armca7pll_d3", "armca7pll_502m", 1, 1),
+
+	FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1),
+	FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1),
+
+	FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "clkph_mck_o", 1, 1),
+	FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2),
+	FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4),
+	FACTOR(CLK_TOP_DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8),
+	FACTOR(CLK_TOP_DMPLL_D16, "dmpll_d16", "clkph_mck_o", 1, 16),
+
+	FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2),
+	FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4),
+	FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8),
+
+	FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1),
+	FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+
+	FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
+	FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+	FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
+	FACTOR(CLK_TOP_MSDCPLL2, "msdcpll2_ck", "msdcpll2", 1, 1),
+	FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2", 1, 2),
+	FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2", 1, 4),
+
+	FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8),
+	FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16),
+	FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4),
+
+	FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll_594m", 1, 1),
+	FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_594m", 1, 2),
+	FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_594m", 1, 4),
+	FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_594m", 1, 8),
+	FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_594m", 1, 16),
+
+	FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2),
+
+	FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, 3),
+	FACTOR(CLK_TOP_VCODECPLL_370P5, "vcodecpll_370p5", "vcodecpll", 1, 4),
+
+	FACTOR(CLK_TOP_VENCPLL, "vencpll_ck", "vencpll", 1, 1),
+	FACTOR(CLK_TOP_VENCPLL_D2, "vencpll_d2", "vencpll", 1, 2),
+	FACTOR(CLK_TOP_VENCPLL_D4, "vencpll_d4", "vencpll", 1, 4),
+};
+
+static const char * const axi_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const mem_parents[] __initconst = {
+	"clk26m",
+	"dmpll_ck"
+};
+
+static const char * const ddrphycfg_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d8"
+};
+
+static const char * const mm_parents[] __initconst = {
+	"clk26m",
+	"vencpll_d2",
+	"main_h364m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll1_d2",
+	"univpll2_d2",
+	"dmpll_d2"
+};
+
+static const char * const pwm_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d4",
+	"univpll3_d2",
+	"univpll1_d4"
+};
+
+static const char * const vdec_parents[] __initconst = {
+	"clk26m",
+	"vcodecpll_ck",
+	"tvdpll_445p5m",
+	"univpll_d3",
+	"vencpll_d2",
+	"syspll_d3",
+	"univpll1_d2",
+	"mmpll_d2",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const venc_parents[] __initconst = {
+	"clk26m",
+	"vcodecpll_ck",
+	"tvdpll_445p5m",
+	"univpll_d3",
+	"vencpll_d2",
+	"syspll_d3",
+	"univpll1_d2",
+	"univpll2_d2",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const mfg_parents[] __initconst = {
+	"clk26m",
+	"mmpll_ck",
+	"dmpll_ck",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"syspll_d3",
+	"syspll1_d2",
+	"syspll_d5",
+	"univpll_d3",
+	"univpll1_d2",
+	"univpll_d5",
+	"univpll2_d2"
+};
+
+static const char * const camtg_parents[] __initconst = {
+	"clk26m",
+	"univpll_d26",
+	"univpll2_d2",
+	"syspll3_d2",
+	"syspll3_d4",
+	"univpll1_d4"
+};
+
+static const char * const uart_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8"
+};
+
+static const char * const spi_parents[] __initconst = {
+	"clk26m",
+	"syspll3_d2",
+	"syspll1_d4",
+	"syspll4_d2",
+	"univpll3_d2",
+	"univpll2_d4",
+	"univpll1_d8"
+};
+
+static const char * const usb20_parents[] __initconst = {
+	"clk26m",
+	"univpll1_d8",
+	"univpll3_d4"
+};
+
+static const char * const usb30_parents[] __initconst = {
+	"clk26m",
+	"univpll3_d2",
+	"usb_syspll_125m",
+	"univpll2_d4"
+};
+
+static const char * const msdc50_0_h_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll2_d2",
+	"syspll4_d2",
+	"univpll_d5",
+	"univpll1_d4"
+};
+
+static const char * const msdc50_0_parents[] __initconst = {
+	"clk26m",
+	"msdcpll_ck",
+	"msdcpll_d2",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"msdcpll_d4",
+	"vencpll_d4",
+	"tvdpll_ck",
+	"univpll_d2",
+	"univpll1_d2",
+	"mmpll_ck",
+	"msdcpll2_ck",
+	"msdcpll2_d2",
+	"msdcpll2_d4"
+};
+
+static const char * const msdc30_1_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d2",
+	"msdcpll_d4",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll_d7",
+	"vencpll_d4"
+};
+
+static const char * const msdc30_2_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d2",
+	"msdcpll_d4",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll_d7",
+	"vencpll_d2"
+};
+
+static const char * const msdc30_3_parents[] __initconst = {
+	"clk26m",
+	"msdcpll2_ck",
+	"msdcpll2_d2",
+	"univpll2_d2",
+	"msdcpll2_d4",
+	"msdcpll_d4",
+	"univpll1_d4",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll_d7",
+	"vencpll_d4",
+	"msdcpll_ck",
+	"msdcpll_d2",
+	"msdcpll_d4"
+};
+
+static const char * const audio_parents[] __initconst = {
+	"clk26m",
+	"syspll3_d4",
+	"syspll4_d4",
+	"syspll1_d16"
+};
+
+static const char * const aud_intbus_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d4",
+	"syspll4_d2",
+	"univpll3_d2",
+	"univpll2_d8",
+	"dmpll_d4",
+	"dmpll_d8"
+};
+
+static const char * const pmicspi_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d8",
+	"syspll3_d4",
+	"syspll1_d16",
+	"univpll3_d4",
+	"univpll_d26",
+	"dmpll_d8",
+	"dmpll_d16"
+};
+
+static const char * const scp_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"univpll_d5",
+	"syspll_d5",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const atb_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"univpll_d5",
+	"dmpll_d2"
+};
+
+static const char * const venc_lt_parents[] __initconst = {
+	"clk26m",
+	"univpll_d3",
+	"vcodecpll_ck",
+	"tvdpll_445p5m",
+	"vencpll_d2",
+	"syspll_d3",
+	"univpll1_d2",
+	"univpll2_d2",
+	"syspll1_d2",
+	"univpll_d5",
+	"vcodecpll_370p5",
+	"dmpll_ck"
+};
+
+static const char * const dpi0_parents[] __initconst = {
+	"clk26m",
+	"tvdpll_d2",
+	"tvdpll_d4",
+	"clk26m",
+	"clk26m",
+	"tvdpll_d8",
+	"tvdpll_d16"
+};
+
+static const char * const irda_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d4",
+	"syspll2_d4"
+};
+
+static const char * const cci400_parents[] __initconst = {
+	"clk26m",
+	"vencpll_ck",
+	"armca7pll_754m",
+	"armca7pll_502m",
+	"univpll_d2",
+	"syspll_d2",
+	"msdcpll_ck",
+	"dmpll_ck"
+};
+
+static const char * const aud_1_parents[] __initconst = {
+	"clk26m",
+	"apll1_ck",
+	"univpll2_d4",
+	"univpll2_d8"
+};
+
+static const char * const aud_2_parents[] __initconst = {
+	"clk26m",
+	"apll2_ck",
+	"univpll2_d4",
+	"univpll2_d8"
+};
+
+static const char * const mem_mfg_in_parents[] __initconst = {
+	"clk26m",
+	"mmpll_ck",
+	"dmpll_ck",
+	"clk26m"
+};
+
+static const char * const axi_mfg_in_parents[] __initconst = {
+	"clk26m",
+	"axi_sel",
+	"dmpll_d2"
+};
+
+static const char * const scam_parents[] __initconst = {
+	"clk26m",
+	"syspll3_d2",
+	"univpll2_d4",
+	"dmpll_d4"
+};
+
+static const char * const spinfi_ifr_parents[] __initconst = {
+	"clk26m",
+	"univpll2_d8",
+	"univpll3_d4",
+	"syspll4_d2",
+	"univpll2_d4",
+	"univpll3_d2",
+	"syspll1_d4",
+	"univpll1_d4"
+};
+
+static const char * const hdmi_parents[] __initconst = {
+	"clk26m",
+	"hdmitx_dig_cts",
+	"hdmitxpll_d2",
+	"hdmitxpll_d3"
+};
+
+static const char * const dpilvds_parents[] __initconst = {
+	"clk26m",
+	"lvdspll",
+	"lvdspll_d2",
+	"lvdspll_d4",
+	"lvdspll_d8",
+	"fpc_ck"
+};
+
+static const char * const msdc50_2_h_parents[] __initconst = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll2_d2",
+	"syspll4_d2",
+	"univpll_d5",
+	"univpll1_d4"
+};
+
+static const char * const hdcp_parents[] __initconst = {
+	"clk26m",
+	"syspll4_d2",
+	"syspll3_d4",
+	"univpll2_d4"
+};
+
+static const char * const hdcp_24m_parents[] __initconst = {
+	"clk26m",
+	"univpll_d26",
+	"univpll_d52",
+	"univpll2_d8"
+};
+
+static const char * const rtc_parents[] __initconst = {
+	"clkrtc_int",
+	"clkrtc_ext",
+	"clk26m",
+	"univpll3_d8"
+};
+
+static const char * const i2s0_m_ck_parents[] __initconst = {
+	"apll1_div1",
+	"apll2_div1"
+};
+
+static const char * const i2s1_m_ck_parents[] __initconst = {
+	"apll1_div2",
+	"apll2_div2"
+};
+
+static const char * const i2s2_m_ck_parents[] __initconst = {
+	"apll1_div3",
+	"apll2_div3"
+};
+
+static const char * const i2s3_m_ck_parents[] __initconst = {
+	"apll1_div4",
+	"apll2_div4"
+};
+
+static const char * const i2s3_b_ck_parents[] __initconst = {
+	"apll1_div5",
+	"apll2_div5"
+};
+
+static const struct mtk_composite top_muxes[] __initconst = {
+	/* CLK_CFG_0 */
+	MUX(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3),
+	MUX(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 1),
+	MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, 0x0040, 16, 1, 23),
+	MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents, 0x0040, 24, 4, 31),
+	/* CLK_CFG_1 */
+	MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7),
+	MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15),
+	MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0050, 16, 4, 23),
+	MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 24, 4, 31),
+	/* CLK_CFG_2 */
+	MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0060, 0, 3, 7),
+	MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 8, 1, 15),
+	MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 16, 3, 23),
+	MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 24, 2, 31),
+	/* CLK_CFG_3 */
+	MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", usb30_parents, 0x0070, 0, 2, 7),
+	MUX_GATE(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents, 0x0070, 8, 3, 15),
+	MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, 0x0070, 16, 4, 23),
+	MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, 0x0070, 24, 3, 31),
+	/* CLK_CFG_4 */
+	MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents, 0x0080, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents, 0x0080, 8, 4, 15),
+	MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0080, 16, 2, 23),
+	MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, 0x0080, 24, 3, 31),
+	/* CLK_CFG_5 */
+	MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0090, 0, 3, 7 /* 7:5 */),
+	MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x0090, 8, 3, 15),
+	MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, 0x0090, 16, 2, 23),
+	MUX_GATE(CLK_TOP_VENC_LT_SEL, "venclt_sel", venc_lt_parents, 0x0090, 24, 4, 31),
+	/* CLK_CFG_6 */
+	MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x00a0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", cci400_parents, 0x00a0, 16, 3, 23),
+	MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, 0x00a0, 24, 2, 31),
+	/* CLK_CFG_7 */
+	MUX_GATE(CLK_TOP_AUD_2_SEL, "aud_2_sel", aud_2_parents, 0x00b0, 0, 2, 7),
+	MUX_GATE(CLK_TOP_MEM_MFG_IN_SEL, "mem_mfg_in_sel", mem_mfg_in_parents, 0x00b0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_AXI_MFG_IN_SEL, "axi_mfg_in_sel", axi_mfg_in_parents, 0x00b0, 16, 2, 23),
+	MUX_GATE(CLK_TOP_SCAM_SEL, "scam_sel", scam_parents, 0x00b0, 24, 2, 31),
+	/* CLK_CFG_12 */
+	MUX_GATE(CLK_TOP_SPINFI_IFR_SEL, "spinfi_ifr_sel", spinfi_ifr_parents, 0x00c0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents, 0x00c0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x00c0, 24, 3, 31),
+	/* CLK_CFG_13 */
+	MUX_GATE(CLK_TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents, 0x00d0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel", hdcp_parents, 0x00d0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel", hdcp_24m_parents, 0x00d0, 16, 2, 23),
+	MUX(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00d0, 24, 2),
+
+	DIV_GATE(CLK_TOP_APLL1_DIV0, "apll1_div0", "aud_1_sel", 0x12c, 8, 0x120, 4, 24),
+	DIV_GATE(CLK_TOP_APLL1_DIV1, "apll1_div1", "aud_1_sel", 0x12c, 9, 0x124, 8, 0),
+	DIV_GATE(CLK_TOP_APLL1_DIV2, "apll1_div2", "aud_1_sel", 0x12c, 10, 0x124, 8, 8),
+	DIV_GATE(CLK_TOP_APLL1_DIV3, "apll1_div3", "aud_1_sel", 0x12c, 11, 0x124, 8, 16),
+	DIV_GATE(CLK_TOP_APLL1_DIV4, "apll1_div4", "aud_1_sel", 0x12c, 12, 0x124, 8, 24),
+	DIV_GATE(CLK_TOP_APLL1_DIV5, "apll1_div5", "apll1_div4", 0x12c, 13, 0x12c, 4, 0),
+
+	DIV_GATE(CLK_TOP_APLL2_DIV0, "apll2_div0", "aud_2_sel", 0x12c, 16, 0x120, 4, 28),
+	DIV_GATE(CLK_TOP_APLL2_DIV1, "apll2_div1", "aud_2_sel", 0x12c, 17, 0x128, 8, 0),
+	DIV_GATE(CLK_TOP_APLL2_DIV2, "apll2_div2", "aud_2_sel", 0x12c, 18, 0x128, 8, 8),
+	DIV_GATE(CLK_TOP_APLL2_DIV3, "apll2_div3", "aud_2_sel", 0x12c, 19, 0x128, 8, 16),
+	DIV_GATE(CLK_TOP_APLL2_DIV4, "apll2_div4", "aud_2_sel", 0x12c, 20, 0x128, 8, 24),
+	DIV_GATE(CLK_TOP_APLL2_DIV5, "apll2_div5", "apll2_div4", 0x12c, 21, 0x12c, 4, 4),
+
+	MUX(CLK_TOP_I2S0_M_SEL, "i2s0_m_ck_sel", i2s0_m_ck_parents, 0x120, 4, 1),
+	MUX(CLK_TOP_I2S1_M_SEL, "i2s1_m_ck_sel", i2s1_m_ck_parents, 0x120, 5, 1),
+	MUX(CLK_TOP_I2S2_M_SEL, "i2s2_m_ck_sel", i2s2_m_ck_parents, 0x120, 6, 1),
+	MUX(CLK_TOP_I2S3_M_SEL, "i2s3_m_ck_sel", i2s3_m_ck_parents, 0x120, 7, 1),
+	MUX(CLK_TOP_I2S3_B_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1),
+};
+
+static const struct mtk_gate_regs infra_cg_regs = {
+	.set_ofs = 0x0040,
+	.clr_ofs = 0x0044,
+	.sta_ofs = 0x0048,
+};
+
+#define GATE_ICG(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &infra_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+static const struct mtk_gate infra_clks[] __initconst = {
+	GATE_ICG(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0),
+	GATE_ICG(CLK_INFRA_SMI, "infra_smi", "mm_sel", 1),
+	GATE_ICG(CLK_INFRA_AUDIO, "infra_audio", "aud_intbus_sel", 5),
+	GATE_ICG(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6),
+	GATE_ICG(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7),
+	GATE_ICG(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8),
+	GATE_ICG(CLK_INFRA_CPUM, "infra_cpum", "clk_null", 15),
+	GATE_ICG(CLK_INFRA_KP, "infra_kp", "axi_sel", 16),
+	GATE_ICG(CLK_INFRA_CEC, "infra_cec", "clk26m", 18),
+	GATE_ICG(CLK_INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22),
+	GATE_ICG(CLK_INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23),
+};
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x0010,
+	.sta_ofs = 0x0018,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+	.set_ofs = 0x000c,
+	.clr_ofs = 0x0014,
+	.sta_ofs = 0x001c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &peri0_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+#define GATE_PERI1(_id, _name, _parent, _shift) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.regs = &peri1_cg_regs,				\
+		.shift = _shift,				\
+		.ops = &mtk_clk_gate_ops_setclr,		\
+	}
+
+static const struct mtk_gate peri_gates[] __initconst = {
+	/* PERI0 */
+	GATE_PERI0(CLK_PERI_NFI, "peri_nfi", "axi_sel", 0),
+	GATE_PERI0(CLK_PERI_THERM, "peri_therm", "axi_sel", 1),
+	GATE_PERI0(CLK_PERI_PWM1, "peri_pwm1", "axi_sel", 2),
+	GATE_PERI0(CLK_PERI_PWM2, "peri_pwm2", "axi_sel", 3),
+	GATE_PERI0(CLK_PERI_PWM3, "peri_pwm3", "axi_sel", 4),
+	GATE_PERI0(CLK_PERI_PWM4, "peri_pwm4", "axi_sel", 5),
+	GATE_PERI0(CLK_PERI_PWM5, "peri_pwm5", "axi_sel", 6),
+	GATE_PERI0(CLK_PERI_PWM6, "peri_pwm6", "axi_sel", 7),
+	GATE_PERI0(CLK_PERI_PWM7, "peri_pwm7", "axi_sel", 8),
+	GATE_PERI0(CLK_PERI_PWM, "peri_pwm", "axi_sel", 9),
+	GATE_PERI0(CLK_PERI_USB0, "peri_usb0", "usb20_sel", 10),
+	GATE_PERI0(CLK_PERI_USB1, "peri_usb1", "usb20_sel", 11),
+	GATE_PERI0(CLK_PERI_AP_DMA, "peri_ap_dma", "axi_sel", 12),
+	GATE_PERI0(CLK_PERI_MSDC30_0, "peri_msdc30_0", "msdc50_0_sel", 13),
+	GATE_PERI0(CLK_PERI_MSDC30_1, "peri_msdc30_1", "msdc30_1_sel", 14),
+	GATE_PERI0(CLK_PERI_MSDC30_2, "peri_msdc30_2", "msdc30_2_sel", 15),
+	GATE_PERI0(CLK_PERI_MSDC30_3, "peri_msdc30_3", "msdc30_3_sel", 16),
+	GATE_PERI0(CLK_PERI_NLI_ARB, "peri_nli_arb", "axi_sel", 17),
+	GATE_PERI0(CLK_PERI_IRDA, "peri_irda", "irda_sel", 18),
+	GATE_PERI0(CLK_PERI_UART0, "peri_uart0", "axi_sel", 19),
+	GATE_PERI0(CLK_PERI_UART1, "peri_uart1", "axi_sel", 20),
+	GATE_PERI0(CLK_PERI_UART2, "peri_uart2", "axi_sel", 21),
+	GATE_PERI0(CLK_PERI_UART3, "peri_uart3", "axi_sel", 22),
+	GATE_PERI0(CLK_PERI_I2C0, "peri_i2c0", "axi_sel", 23),
+	GATE_PERI0(CLK_PERI_I2C1, "peri_i2c1", "axi_sel", 24),
+	GATE_PERI0(CLK_PERI_I2C2, "peri_i2c2", "axi_sel", 25),
+	GATE_PERI0(CLK_PERI_I2C3, "peri_i2c3", "axi_sel", 26),
+	GATE_PERI0(CLK_PERI_I2C4, "peri_i2c4", "axi_sel", 27),
+	GATE_PERI0(CLK_PERI_AUXADC, "peri_auxadc", "clk26m", 28),
+	GATE_PERI0(CLK_PERI_SPI0, "peri_spi0", "spi_sel", 29),
+	GATE_PERI0(CLK_PERI_I2C5, "peri_i2c5", "axi_sel", 30),
+	GATE_PERI0(CLK_PERI_NFIECC, "peri_nfiecc", "axi_sel", 31),
+	/* PERI1 */
+	GATE_PERI1(CLK_PERI_SPI, "peri_spi", "spi_sel", 0),
+	GATE_PERI1(CLK_PERI_IRRX, "peri_irrx", "spi_sel", 1),
+	GATE_PERI1(CLK_PERI_I2C6, "peri_i2c6", "axi_sel", 2),
+};
+
+static const char * const uart_ck_sel_parents[] __initconst = {
+	"clk26m",
+	"uart_sel",
+};
+
+static const struct mtk_composite peri_clks[] __initconst = {
+	MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1),
+	MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1),
+	MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1),
+	MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
+};
+
+static void __init mtk_topckgen_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	int r;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+
+	mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
+	mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
+	mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
+			&mt8173_clk_lock, clk_data);
+
+	clk_prepare_enable(clk_data->clks[CLK_TOP_CCI400_SEL]);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init);
+
+static void __init mtk_infrasys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+
+	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+
+	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0x30);
+}
+CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8173-infracfg", mtk_infrasys_init);
+
+static void __init mtk_pericfg_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	void __iomem *base;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("%s(): ioremap failed\n", __func__);
+		return;
+	}
+
+	clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+
+	mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
+						clk_data);
+	mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base,
+			&mt8173_clk_lock, clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+
+	mtk_register_reset_controller(node, 2, 0);
+}
+CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
+
+#define MT8173_PLL_FMAX		(3000UL * MHZ)
+
+#define CON0_MT8173_RST_BAR	BIT(24)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, \
+			_tuner_reg, _pcw_reg, _pcw_shift) { \
+		.id = _id,						\
+		.name = _name,						\
+		.reg = _reg,						\
+		.pwr_reg = _pwr_reg,					\
+		.en_mask = _en_mask,					\
+		.flags = _flags,					\
+		.rst_bar_mask = CON0_MT8173_RST_BAR,			\
+		.fmax = MT8173_PLL_FMAX,				\
+		.pcwbits = _pcwbits,					\
+		.pd_reg = _pd_reg,					\
+		.pd_shift = _pd_shift,					\
+		.tuner_reg = _tuner_reg,				\
+		.pcw_reg = _pcw_reg,					\
+		.pcw_shift = _pcw_shift,				\
+	}
+
+static const struct mtk_pll_data plls[] = {
+	PLL(CLK_APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0),
+	PLL(CLK_APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0x00000001, 0, 21, 0x214, 24, 0x0, 0x214, 0),
+	PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0),
+	PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000001, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14),
+	PLL(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0),
+	PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0x00000001, 0, 21, 0x250, 4, 0x0, 0x254, 0),
+	PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0x00000001, 0, 21, 0x260, 4, 0x0, 0x264, 0),
+	PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0x00000001, 0, 21, 0x270, 4, 0x0, 0x274, 0),
+	PLL(CLK_APMIXED_MPLL, "mpll", 0x280, 0x28c, 0x00000001, 0, 21, 0x280, 4, 0x0, 0x284, 0),
+	PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0x00000001, 0, 21, 0x290, 4, 0x0, 0x294, 0),
+	PLL(CLK_APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0x00000001, 0, 31, 0x2a0, 4, 0x2a4, 0x2a4, 0),
+	PLL(CLK_APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0x00000001, 0, 31, 0x2b4, 4, 0x2b8, 0x2b8, 0),
+	PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2d0, 0x2dc, 0x00000001, 0, 21, 0x2d0, 4, 0x0, 0x2d4, 0),
+	PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x2f0, 0x2fc, 0x00000001, 0, 21, 0x2f0, 4, 0x0, 0x2f4, 0),
+};
+
+static void __init mtk_apmixedsys_init(struct device_node *node)
+{
+	struct clk_onecell_data *clk_data;
+
+	clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
+	if (!clk_data)
+		return;
+
+	mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+
+	clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMCA15PLL]);
+}
+CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
+		mtk_apmixedsys_init);
diff --git a/include/dt-bindings/clock/mt8173-clk.h b/include/dt-bindings/clock/mt8173-clk.h
new file mode 100644
index 000000000000..4ad76ed882ad
--- /dev/null
+++ b/include/dt-bindings/clock/mt8173-clk.h
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: James Liao <jamesjj.liao@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT8173_H
+#define _DT_BINDINGS_CLK_MT8173_H
+
+/* TOPCKGEN */
+
+#define CLK_TOP_CLKPH_MCK_O		1
+#define CLK_TOP_DPI			2
+#define CLK_TOP_USB_SYSPLL_125M		3
+#define CLK_TOP_HDMITX_DIG_CTS		4
+#define CLK_TOP_ARMCA7PLL_754M		5
+#define CLK_TOP_ARMCA7PLL_502M		6
+#define CLK_TOP_MAIN_H546M		7
+#define CLK_TOP_MAIN_H364M		8
+#define CLK_TOP_MAIN_H218P4M		9
+#define CLK_TOP_MAIN_H156M		10
+#define CLK_TOP_TVDPLL_445P5M		11
+#define CLK_TOP_TVDPLL_594M		12
+#define CLK_TOP_UNIV_624M		13
+#define CLK_TOP_UNIV_416M		14
+#define CLK_TOP_UNIV_249P6M		15
+#define CLK_TOP_UNIV_178P3M		16
+#define CLK_TOP_UNIV_48M		17
+#define CLK_TOP_CLKRTC_EXT		18
+#define CLK_TOP_CLKRTC_INT		19
+#define CLK_TOP_FPC			20
+#define CLK_TOP_HDMITXPLL_D2		21
+#define CLK_TOP_HDMITXPLL_D3		22
+#define CLK_TOP_ARMCA7PLL_D2		23
+#define CLK_TOP_ARMCA7PLL_D3		24
+#define CLK_TOP_APLL1			25
+#define CLK_TOP_APLL2			26
+#define CLK_TOP_DMPLL			27
+#define CLK_TOP_DMPLL_D2		28
+#define CLK_TOP_DMPLL_D4		29
+#define CLK_TOP_DMPLL_D8		30
+#define CLK_TOP_DMPLL_D16		31
+#define CLK_TOP_LVDSPLL_D2		32
+#define CLK_TOP_LVDSPLL_D4		33
+#define CLK_TOP_LVDSPLL_D8		34
+#define CLK_TOP_MMPLL			35
+#define CLK_TOP_MMPLL_D2		36
+#define CLK_TOP_MSDCPLL			37
+#define CLK_TOP_MSDCPLL_D2		38
+#define CLK_TOP_MSDCPLL_D4		39
+#define CLK_TOP_MSDCPLL2		40
+#define CLK_TOP_MSDCPLL2_D2		41
+#define CLK_TOP_MSDCPLL2_D4		42
+#define CLK_TOP_SYSPLL_D2		43
+#define CLK_TOP_SYSPLL1_D2		44
+#define CLK_TOP_SYSPLL1_D4		45
+#define CLK_TOP_SYSPLL1_D8		46
+#define CLK_TOP_SYSPLL1_D16		47
+#define CLK_TOP_SYSPLL_D3		48
+#define CLK_TOP_SYSPLL2_D2		49
+#define CLK_TOP_SYSPLL2_D4		50
+#define CLK_TOP_SYSPLL_D5		51
+#define CLK_TOP_SYSPLL3_D2		52
+#define CLK_TOP_SYSPLL3_D4		53
+#define CLK_TOP_SYSPLL_D7		54
+#define CLK_TOP_SYSPLL4_D2		55
+#define CLK_TOP_SYSPLL4_D4		56
+#define CLK_TOP_TVDPLL			57
+#define CLK_TOP_TVDPLL_D2		58
+#define CLK_TOP_TVDPLL_D4		59
+#define CLK_TOP_TVDPLL_D8		60
+#define CLK_TOP_TVDPLL_D16		61
+#define CLK_TOP_UNIVPLL_D2		62
+#define CLK_TOP_UNIVPLL1_D2		63
+#define CLK_TOP_UNIVPLL1_D4		64
+#define CLK_TOP_UNIVPLL1_D8		65
+#define CLK_TOP_UNIVPLL_D3		66
+#define CLK_TOP_UNIVPLL2_D2		67
+#define CLK_TOP_UNIVPLL2_D4		68
+#define CLK_TOP_UNIVPLL2_D8		69
+#define CLK_TOP_UNIVPLL_D5		70
+#define CLK_TOP_UNIVPLL3_D2		71
+#define CLK_TOP_UNIVPLL3_D4		72
+#define CLK_TOP_UNIVPLL3_D8		73
+#define CLK_TOP_UNIVPLL_D7		74
+#define CLK_TOP_UNIVPLL_D26		75
+#define CLK_TOP_UNIVPLL_D52		76
+#define CLK_TOP_VCODECPLL		77
+#define CLK_TOP_VCODECPLL_370P5		78
+#define CLK_TOP_VENCPLL			79
+#define CLK_TOP_VENCPLL_D2		80
+#define CLK_TOP_VENCPLL_D4		81
+#define CLK_TOP_AXI_SEL			82
+#define CLK_TOP_MEM_SEL			83
+#define CLK_TOP_DDRPHYCFG_SEL		84
+#define CLK_TOP_MM_SEL			85
+#define CLK_TOP_PWM_SEL			86
+#define CLK_TOP_VDEC_SEL		87
+#define CLK_TOP_VENC_SEL		88
+#define CLK_TOP_MFG_SEL			89
+#define CLK_TOP_CAMTG_SEL		90
+#define CLK_TOP_UART_SEL		91
+#define CLK_TOP_SPI_SEL			92
+#define CLK_TOP_USB20_SEL		93
+#define CLK_TOP_USB30_SEL		94
+#define CLK_TOP_MSDC50_0_H_SEL		95
+#define CLK_TOP_MSDC50_0_SEL		96
+#define CLK_TOP_MSDC30_1_SEL		97
+#define CLK_TOP_MSDC30_2_SEL		98
+#define CLK_TOP_MSDC30_3_SEL		99
+#define CLK_TOP_AUDIO_SEL		100
+#define CLK_TOP_AUD_INTBUS_SEL		101
+#define CLK_TOP_PMICSPI_SEL		102
+#define CLK_TOP_SCP_SEL			103
+#define CLK_TOP_ATB_SEL			104
+#define CLK_TOP_VENC_LT_SEL		105
+#define CLK_TOP_DPI0_SEL		106
+#define CLK_TOP_IRDA_SEL		107
+#define CLK_TOP_CCI400_SEL		108
+#define CLK_TOP_AUD_1_SEL		109
+#define CLK_TOP_AUD_2_SEL		110
+#define CLK_TOP_MEM_MFG_IN_SEL		111
+#define CLK_TOP_AXI_MFG_IN_SEL		112
+#define CLK_TOP_SCAM_SEL		113
+#define CLK_TOP_SPINFI_IFR_SEL		114
+#define CLK_TOP_HDMI_SEL		115
+#define CLK_TOP_DPILVDS_SEL		116
+#define CLK_TOP_MSDC50_2_H_SEL		117
+#define CLK_TOP_HDCP_SEL		118
+#define CLK_TOP_HDCP_24M_SEL		119
+#define CLK_TOP_RTC_SEL			120
+#define CLK_TOP_APLL1_DIV0		121
+#define CLK_TOP_APLL1_DIV1		122
+#define CLK_TOP_APLL1_DIV2		123
+#define CLK_TOP_APLL1_DIV3		124
+#define CLK_TOP_APLL1_DIV4		125
+#define CLK_TOP_APLL1_DIV5		126
+#define CLK_TOP_APLL2_DIV0		127
+#define CLK_TOP_APLL2_DIV1		128
+#define CLK_TOP_APLL2_DIV2		129
+#define CLK_TOP_APLL2_DIV3		130
+#define CLK_TOP_APLL2_DIV4		131
+#define CLK_TOP_APLL2_DIV5		132
+#define CLK_TOP_I2S0_M_SEL		133
+#define CLK_TOP_I2S1_M_SEL		134
+#define CLK_TOP_I2S2_M_SEL		135
+#define CLK_TOP_I2S3_M_SEL		136
+#define CLK_TOP_I2S3_B_SEL		137
+#define CLK_TOP_NR_CLK			138
+
+/* APMIXED_SYS */
+
+#define CLK_APMIXED_ARMCA15PLL	1
+#define CLK_APMIXED_ARMCA7PLL	2
+#define CLK_APMIXED_MAINPLL		3
+#define CLK_APMIXED_UNIVPLL		4
+#define CLK_APMIXED_MMPLL		5
+#define CLK_APMIXED_MSDCPLL		6
+#define CLK_APMIXED_VENCPLL		7
+#define CLK_APMIXED_TVDPLL		8
+#define CLK_APMIXED_MPLL		9
+#define CLK_APMIXED_VCODECPLL		10
+#define CLK_APMIXED_APLL1		11
+#define CLK_APMIXED_APLL2		12
+#define CLK_APMIXED_LVDSPLL		13
+#define CLK_APMIXED_MSDCPLL2		14
+#define CLK_APMIXED_NR_CLK		15
+
+/* INFRA_SYS */
+
+#define CLK_INFRA_DBGCLK		1
+#define CLK_INFRA_SMI			2
+#define CLK_INFRA_AUDIO			3
+#define CLK_INFRA_GCE			4
+#define CLK_INFRA_L2C_SRAM		5
+#define CLK_INFRA_M4U			6
+#define CLK_INFRA_CPUM			7
+#define CLK_INFRA_KP			8
+#define CLK_INFRA_CEC			9
+#define CLK_INFRA_PMICSPI		10
+#define CLK_INFRA_PMICWRAP		11
+#define CLK_INFRA_NR_CLK		12
+
+/* PERI_SYS */
+
+#define CLK_PERI_NFI			1
+#define CLK_PERI_THERM			2
+#define CLK_PERI_PWM1			3
+#define CLK_PERI_PWM2			4
+#define CLK_PERI_PWM3			5
+#define CLK_PERI_PWM4			6
+#define CLK_PERI_PWM5			7
+#define CLK_PERI_PWM6			8
+#define CLK_PERI_PWM7			9
+#define CLK_PERI_PWM			10
+#define CLK_PERI_USB0			11
+#define CLK_PERI_USB1			12
+#define CLK_PERI_AP_DMA			13
+#define CLK_PERI_MSDC30_0		14
+#define CLK_PERI_MSDC30_1		15
+#define CLK_PERI_MSDC30_2		16
+#define CLK_PERI_MSDC30_3		17
+#define CLK_PERI_NLI_ARB		18
+#define CLK_PERI_IRDA			19
+#define CLK_PERI_UART0			20
+#define CLK_PERI_UART1			21
+#define CLK_PERI_UART2			22
+#define CLK_PERI_UART3			23
+#define CLK_PERI_I2C0			24
+#define CLK_PERI_I2C1			25
+#define CLK_PERI_I2C2			26
+#define CLK_PERI_I2C3			27
+#define CLK_PERI_I2C4			28
+#define CLK_PERI_AUXADC			29
+#define CLK_PERI_SPI0			30
+#define CLK_PERI_I2C5			31
+#define CLK_PERI_NFIECC			32
+#define CLK_PERI_SPI			33
+#define CLK_PERI_IRRX			34
+#define CLK_PERI_I2C6			35
+#define CLK_PERI_UART0_SEL		36
+#define CLK_PERI_UART1_SEL		37
+#define CLK_PERI_UART2_SEL		38
+#define CLK_PERI_UART3_SEL		39
+#define CLK_PERI_NR_CLK			40
+
+#endif /* _DT_BINDINGS_CLK_MT8173_H */
diff --git a/include/dt-bindings/reset-controller/mt8173-resets.h b/include/dt-bindings/reset-controller/mt8173-resets.h
new file mode 100644
index 000000000000..9464b37cf68c
--- /dev/null
+++ b/include/dt-bindings/reset-controller/mt8173-resets.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora Fu, MediaTek
+ *
+ * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8173
+#define _DT_BINDINGS_RESET_CONTROLLER_MT8173
+
+/* INFRACFG resets */
+#define MT8173_INFRA_EMI_REG_RST        0
+#define MT8173_INFRA_DRAMC0_A0_RST      1
+#define MT8173_INFRA_APCIRQ_EINT_RST    3
+#define MT8173_INFRA_APXGPT_RST         4
+#define MT8173_INFRA_SCPSYS_RST         5
+#define MT8173_INFRA_KP_RST             6
+#define MT8173_INFRA_PMIC_WRAP_RST      7
+#define MT8173_INFRA_MPIP_RST           8
+#define MT8173_INFRA_CEC_RST            9
+#define MT8173_INFRA_EMI_RST            32
+#define MT8173_INFRA_DRAMC0_RST         34
+#define MT8173_INFRA_APMIXEDSYS_RST     35
+#define MT8173_INFRA_MIPI_DSI_RST       36
+#define MT8173_INFRA_TRNG_RST           37
+#define MT8173_INFRA_SYSIRQ_RST         38
+#define MT8173_INFRA_MIPI_CSI_RST       39
+#define MT8173_INFRA_GCE_FAXI_RST       40
+#define MT8173_INFRA_MMIOMMURST         47
+
+
+/*  PERICFG resets */
+#define MT8173_PERI_UART0_SW_RST        0
+#define MT8173_PERI_UART1_SW_RST        1
+#define MT8173_PERI_UART2_SW_RST        2
+#define MT8173_PERI_UART3_SW_RST        3
+#define MT8173_PERI_IRRX_SW_RST         4
+#define MT8173_PERI_PWM_SW_RST          8
+#define MT8173_PERI_AUXADC_SW_RST       10
+#define MT8173_PERI_DMA_SW_RST          11
+#define MT8173_PERI_I2C6_SW_RST         13
+#define MT8173_PERI_NFI_SW_RST          14
+#define MT8173_PERI_THERM_SW_RST        16
+#define MT8173_PERI_MSDC2_SW_RST        17
+#define MT8173_PERI_MSDC3_SW_RST        18
+#define MT8173_PERI_MSDC0_SW_RST        19
+#define MT8173_PERI_MSDC1_SW_RST        20
+#define MT8173_PERI_I2C0_SW_RST         22
+#define MT8173_PERI_I2C1_SW_RST         23
+#define MT8173_PERI_I2C2_SW_RST         24
+#define MT8173_PERI_I2C3_SW_RST         25
+#define MT8173_PERI_I2C4_SW_RST         26
+#define MT8173_PERI_HDMI_SW_RST         29
+#define MT8173_PERI_SPI0_SW_RST         33
+
+#endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT8173 */

From 9eb67f1093fdaefdffe56861e373f50d117352e9 Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer@pengutronix.de>
Date: Thu, 23 Apr 2015 10:35:43 +0200
Subject: [PATCH 015/135] dt-bindings: ARM: Mediatek: Document devicetree
 bindings for clock/reset controllers

This adds the binding documentation for the apmixedsys, perisys and
infracfg controllers found on Mediatek SoCs.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 .../arm/mediatek/mediatek,apmixedsys.txt      | 23 ++++++++++++++
 .../arm/mediatek/mediatek,infracfg.txt        | 30 +++++++++++++++++++
 .../arm/mediatek/mediatek,pericfg.txt         | 30 +++++++++++++++++++
 .../arm/mediatek/mediatek,topckgen.txt        | 23 ++++++++++++++
 4 files changed, 106 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
 create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt

diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
new file mode 100644
index 000000000000..5af6d7394608
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
@@ -0,0 +1,23 @@
+Mediatek apmixedsys controller
+==============================
+
+The Mediatek apmixedsys controller provides the PLLs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-apmixedsys"
+	- "mediatek,mt8173-apmixedsys"
+- #clock-cells: Must be 1
+
+The apmixedsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+apmixedsys: apmixedsys@10209000 {
+	compatible = "mediatek,mt8173-apmixedsys";
+	reg = <0 0x10209000 0 0x1000>;
+	#clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
new file mode 100644
index 000000000000..684da473b3e8
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
@@ -0,0 +1,30 @@
+Mediatek infracfg controller
+============================
+
+The Mediatek infracfg controller provides various clocks and reset
+outputs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-infracfg", "syscon"
+	- "mediatek,mt8173-infracfg", "syscon"
+- #clock-cells: Must be 1
+- #reset-cells: Must be 1
+
+The infracfg controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+Also it uses the common reset controller binding from
+Documentation/devicetree/bindings/reset/reset.txt.
+The available reset outputs are defined in
+dt-bindings/reset-controller/mt*-resets.h
+
+Example:
+
+infracfg: infracfg@10001000 {
+	compatible = "mediatek,mt8173-infracfg", "syscon";
+	reg = <0 0x10001000 0 0x1000>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
new file mode 100644
index 000000000000..fdb45c6b63de
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
@@ -0,0 +1,30 @@
+Mediatek pericfg controller
+===========================
+
+The Mediatek pericfg controller provides various clocks and reset
+outputs to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-pericfg", "syscon"
+	- "mediatek,mt8173-pericfg", "syscon"
+- #clock-cells: Must be 1
+- #reset-cells: Must be 1
+
+The pericfg controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+Also it uses the common reset controller binding from
+Documentation/devicetree/bindings/reset/reset.txt.
+The available reset outputs are defined in
+dt-bindings/reset-controller/mt*-resets.h
+
+Example:
+
+pericfg: pericfg@10003000 {
+	compatible = "mediatek,mt8173-pericfg", "syscon";
+	reg = <0 0x10003000 0 0x1000>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
new file mode 100644
index 000000000000..a4252489860d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
@@ -0,0 +1,23 @@
+Mediatek topckgen controller
+============================
+
+The Mediatek topckgen controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be:
+	- "mediatek,mt8135-topckgen"
+	- "mediatek,mt8173-topckgen"
+- #clock-cells: Must be 1
+
+The topckgen controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+topckgen: topckgen@10000000 {
+	compatible = "mediatek,mt8173-topckgen";
+	reg = <0 0x10000000 0 0x1000>;
+	#clock-cells = <1>;
+};

From 9b030bc92999853bae91262908554f168fa74965 Mon Sep 17 00:00:00 2001
From: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Date: Tue, 28 Apr 2015 13:46:16 +0900
Subject: [PATCH 016/135] clk: rockchip: Staticize file-scope declarations

Add missing static to local (file-scope only) symbols.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/rockchip/clk-rk3188.c | 2 +-
 drivers/clk/rockchip/clk-rk3288.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index 556ce041d371..e4f9d472f1ff 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -26,7 +26,7 @@ enum rk3188_plls {
 	apll, cpll, dpll, gpll,
 };
 
-struct rockchip_pll_rate_table rk3188_pll_rates[] = {
+static struct rockchip_pll_rate_table rk3188_pll_rates[] = {
 	RK3066_PLL_RATE(2208000000, 1, 92, 1),
 	RK3066_PLL_RATE(2184000000, 1, 91, 1),
 	RK3066_PLL_RATE(2160000000, 1, 90, 1),
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index d17eb4528a28..4f817ed9e6ee 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -27,7 +27,7 @@ enum rk3288_plls {
 	apll, dpll, cpll, gpll, npll,
 };
 
-struct rockchip_pll_rate_table rk3288_pll_rates[] = {
+static struct rockchip_pll_rate_table rk3288_pll_rates[] = {
 	RK3066_PLL_RATE(2208000000, 1, 92, 1),
 	RK3066_PLL_RATE(2184000000, 1, 91, 1),
 	RK3066_PLL_RATE(2160000000, 1, 90, 1),

From 6b8f9eabec1c77ab72194b1bacff5d5c6e16dbf8 Mon Sep 17 00:00:00 2001
From: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Date: Tue, 28 Apr 2015 13:46:17 +0900
Subject: [PATCH 017/135] clk: exynos: Staticize file-scope declarations

Add missing static to local (file-scope only) symbols.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/samsung/clk-exynos5260.c | 74 ++++++++++++++--------------
 drivers/clk/samsung/clk-exynos5420.c | 10 ++--
 2 files changed, 42 insertions(+), 42 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
index e2e5193d1049..df1d83c45554 100644
--- a/drivers/clk/samsung/clk-exynos5260.c
+++ b/drivers/clk/samsung/clk-exynos5260.c
@@ -94,7 +94,7 @@ PNAME(mout_aud_pll_user_p) = {"fin_pll", "fout_aud_pll"};
 PNAME(mout_sclk_aud_i2s_p) = {"mout_aud_pll_user", "ioclk_i2s_cdclk"};
 PNAME(mout_sclk_aud_pcm_p) = {"mout_aud_pll_user", "ioclk_pcm_extclk"};
 
-struct samsung_mux_clock aud_mux_clks[] __initdata = {
+static struct samsung_mux_clock aud_mux_clks[] __initdata = {
 	MUX(AUD_MOUT_AUD_PLL_USER, "mout_aud_pll_user", mout_aud_pll_user_p,
 			MUX_SEL_AUD, 0, 1),
 	MUX(AUD_MOUT_SCLK_AUD_I2S, "mout_sclk_aud_i2s", mout_sclk_aud_i2s_p,
@@ -103,7 +103,7 @@ struct samsung_mux_clock aud_mux_clks[] __initdata = {
 			MUX_SEL_AUD, 8, 1),
 };
 
-struct samsung_div_clock aud_div_clks[] __initdata = {
+static struct samsung_div_clock aud_div_clks[] __initdata = {
 	DIV(AUD_DOUT_ACLK_AUD_131, "dout_aclk_aud_131", "mout_aud_pll_user",
 			DIV_AUD0, 0, 4),
 
@@ -115,7 +115,7 @@ struct samsung_div_clock aud_div_clks[] __initdata = {
 			DIV_AUD1, 12, 4),
 };
 
-struct samsung_gate_clock aud_gate_clks[] __initdata = {
+static struct samsung_gate_clock aud_gate_clks[] __initdata = {
 	GATE(AUD_SCLK_I2S, "sclk_aud_i2s", "dout_sclk_aud_i2s",
 			EN_SCLK_AUD, 0, CLK_SET_RATE_PARENT, 0),
 	GATE(AUD_SCLK_PCM, "sclk_aud_pcm", "dout_sclk_aud_pcm",
@@ -203,7 +203,7 @@ PNAME(mout_phyclk_mipi_dphy_4lmrxclk_esc0_user_p) = {"fin_pll",
 PNAME(mout_sclk_hdmi_spdif_p) = {"fin_pll", "ioclk_spdif_extclk",
 			"dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"};
 
-struct samsung_mux_clock disp_mux_clks[] __initdata = {
+static struct samsung_mux_clock disp_mux_clks[] __initdata = {
 	MUX(DISP_MOUT_ACLK_DISP_333_USER, "mout_aclk_disp_333_user",
 			mout_aclk_disp_333_user_p,
 			MUX_SEL_DISP0, 0, 1),
@@ -272,7 +272,7 @@ struct samsung_mux_clock disp_mux_clks[] __initdata = {
 			MUX_SEL_DISP4, 4, 2),
 };
 
-struct samsung_div_clock disp_div_clks[] __initdata = {
+static struct samsung_div_clock disp_div_clks[] __initdata = {
 	DIV(DISP_DOUT_PCLK_DISP_111, "dout_pclk_disp_111",
 			"mout_aclk_disp_222_user",
 			DIV_DISP, 8, 4),
@@ -285,7 +285,7 @@ struct samsung_div_clock disp_div_clks[] __initdata = {
 			DIV_DISP, 16, 4),
 };
 
-struct samsung_gate_clock disp_gate_clks[] __initdata = {
+static struct samsung_gate_clock disp_gate_clks[] __initdata = {
 	GATE(DISP_MOUT_HDMI_PHY_PIXEL_USER, "sclk_hdmi_link_i_pixel",
 			"mout_phyclk_hdmi_phy_pixel_clko_user",
 			EN_SCLK_DISP0, 26, CLK_SET_RATE_PARENT, 0),
@@ -363,13 +363,13 @@ static unsigned long egl_clk_regs[] __initdata = {
 PNAME(mout_egl_b_p) = {"mout_egl_pll", "dout_bus_pll"};
 PNAME(mout_egl_pll_p) = {"fin_pll", "fout_egl_pll"};
 
-struct samsung_mux_clock egl_mux_clks[] __initdata = {
+static struct samsung_mux_clock egl_mux_clks[] __initdata = {
 	MUX(EGL_MOUT_EGL_PLL, "mout_egl_pll", mout_egl_pll_p,
 			MUX_SEL_EGL, 4, 1),
 	MUX(EGL_MOUT_EGL_B, "mout_egl_b", mout_egl_b_p, MUX_SEL_EGL, 16, 1),
 };
 
-struct samsung_div_clock egl_div_clks[] __initdata = {
+static struct samsung_div_clock egl_div_clks[] __initdata = {
 	DIV(EGL_DOUT_EGL1, "dout_egl1", "mout_egl_b", DIV_EGL, 0, 3),
 	DIV(EGL_DOUT_EGL2, "dout_egl2", "dout_egl1", DIV_EGL, 4, 3),
 	DIV(EGL_DOUT_ACLK_EGL, "dout_aclk_egl", "dout_egl2", DIV_EGL, 8, 3),
@@ -433,7 +433,7 @@ PNAME(mout_phyclk_usbdrd30_pipe_pclk_user_p) = {"fin_pll",
 PNAME(mout_phyclk_usbdrd30_phyclock_user_p) = {"fin_pll",
 			"phyclk_usbdrd30_udrd30_phyclock"};
 
-struct samsung_mux_clock fsys_mux_clks[] __initdata = {
+static struct samsung_mux_clock fsys_mux_clks[] __initdata = {
 	MUX(FSYS_MOUT_PHYCLK_USBDRD30_PHYCLOCK_USER,
 			"mout_phyclk_usbdrd30_phyclock_user",
 			mout_phyclk_usbdrd30_phyclock_user_p,
@@ -456,7 +456,7 @@ struct samsung_mux_clock fsys_mux_clks[] __initdata = {
 			MUX_SEL_FSYS1, 16, 1),
 };
 
-struct samsung_gate_clock fsys_gate_clks[] __initdata = {
+static struct samsung_gate_clock fsys_gate_clks[] __initdata = {
 	GATE(FSYS_PHYCLK_USBHOST20, "phyclk_usbhost20_phyclock",
 			"mout_phyclk_usbdrd30_phyclock_user",
 			EN_SCLK_FSYS, 1, 0, 0),
@@ -537,18 +537,18 @@ static unsigned long g2d_clk_regs[] __initdata = {
 
 PNAME(mout_aclk_g2d_333_user_p) = {"fin_pll", "dout_aclk_g2d_333"};
 
-struct samsung_mux_clock g2d_mux_clks[] __initdata = {
+static struct samsung_mux_clock g2d_mux_clks[] __initdata = {
 	MUX(G2D_MOUT_ACLK_G2D_333_USER, "mout_aclk_g2d_333_user",
 			mout_aclk_g2d_333_user_p,
 			MUX_SEL_G2D, 0, 1),
 };
 
-struct samsung_div_clock g2d_div_clks[] __initdata = {
+static struct samsung_div_clock g2d_div_clks[] __initdata = {
 	DIV(G2D_DOUT_PCLK_G2D_83, "dout_pclk_g2d_83", "mout_aclk_g2d_333_user",
 			DIV_G2D, 0, 3),
 };
 
-struct samsung_gate_clock g2d_gate_clks[] __initdata = {
+static struct samsung_gate_clock g2d_gate_clks[] __initdata = {
 	GATE(G2D_CLK_G2D, "clk_g2d", "mout_aclk_g2d_333_user",
 			EN_IP_G2D, 4, 0, 0),
 	GATE(G2D_CLK_JPEG, "clk_jpeg", "mout_aclk_g2d_333_user",
@@ -617,17 +617,17 @@ static unsigned long g3d_clk_regs[] __initdata = {
 
 PNAME(mout_g3d_pll_p) = {"fin_pll", "fout_g3d_pll"};
 
-struct samsung_mux_clock g3d_mux_clks[] __initdata = {
+static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
 	MUX(G3D_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
 			MUX_SEL_G3D, 0, 1),
 };
 
-struct samsung_div_clock g3d_div_clks[] __initdata = {
+static struct samsung_div_clock g3d_div_clks[] __initdata = {
 	DIV(G3D_DOUT_PCLK_G3D, "dout_pclk_g3d", "dout_aclk_g3d", DIV_G3D, 0, 3),
 	DIV(G3D_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_g3d_pll", DIV_G3D, 4, 3),
 };
 
-struct samsung_gate_clock g3d_gate_clks[] __initdata = {
+static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
 	GATE(G3D_CLK_G3D, "clk_g3d", "dout_aclk_g3d", EN_IP_G3D, 2, 0, 0),
 	GATE(G3D_CLK_G3D_HPM, "clk_g3d_hpm", "dout_aclk_g3d",
 			EN_IP_G3D, 3, 0, 0),
@@ -694,7 +694,7 @@ PNAME(mout_aclk_m2m_400_user_p) = {"fin_pll", "dout_aclk_gscl_400"};
 PNAME(mout_aclk_gscl_fimc_user_p) = {"fin_pll", "dout_aclk_gscl_400"};
 PNAME(mout_aclk_csis_p) = {"dout_aclk_csis_200", "mout_aclk_gscl_fimc_user"};
 
-struct samsung_mux_clock gscl_mux_clks[] __initdata = {
+static struct samsung_mux_clock gscl_mux_clks[] __initdata = {
 	MUX(GSCL_MOUT_ACLK_GSCL_333_USER, "mout_aclk_gscl_333_user",
 			mout_aclk_gscl_333_user_p,
 			MUX_SEL_GSCL, 0, 1),
@@ -708,7 +708,7 @@ struct samsung_mux_clock gscl_mux_clks[] __initdata = {
 			MUX_SEL_GSCL, 24, 1),
 };
 
-struct samsung_div_clock gscl_div_clks[] __initdata = {
+static struct samsung_div_clock gscl_div_clks[] __initdata = {
 	DIV(GSCL_DOUT_PCLK_M2M_100, "dout_pclk_m2m_100",
 			"mout_aclk_m2m_400_user",
 			DIV_GSCL, 0, 3),
@@ -717,7 +717,7 @@ struct samsung_div_clock gscl_div_clks[] __initdata = {
 			DIV_GSCL, 4, 3),
 };
 
-struct samsung_gate_clock gscl_gate_clks[] __initdata = {
+static struct samsung_gate_clock gscl_gate_clks[] __initdata = {
 	GATE(GSCL_SCLK_CSIS0_WRAP, "sclk_csis0_wrap", "dout_aclk_csis_200",
 			EN_SCLK_GSCL_FIMC, 0, CLK_SET_RATE_PARENT, 0),
 	GATE(GSCL_SCLK_CSIS1_WRAP, "sclk_csis1_wrap", "dout_aclk_csis_200",
@@ -813,14 +813,14 @@ static unsigned long isp_clk_regs[] __initdata = {
 PNAME(mout_isp_400_user_p) = {"fin_pll", "dout_aclk_isp1_400"};
 PNAME(mout_isp_266_user_p)	 = {"fin_pll", "dout_aclk_isp1_266"};
 
-struct samsung_mux_clock isp_mux_clks[] __initdata = {
+static struct samsung_mux_clock isp_mux_clks[] __initdata = {
 	MUX(ISP_MOUT_ISP_266_USER, "mout_isp_266_user", mout_isp_266_user_p,
 			MUX_SEL_ISP0, 0, 1),
 	MUX(ISP_MOUT_ISP_400_USER, "mout_isp_400_user", mout_isp_400_user_p,
 			MUX_SEL_ISP0, 4, 1),
 };
 
-struct samsung_div_clock isp_div_clks[] __initdata = {
+static struct samsung_div_clock isp_div_clks[] __initdata = {
 	DIV(ISP_DOUT_PCLK_ISP_66, "dout_pclk_isp_66", "mout_kfc",
 			DIV_ISP, 0, 3),
 	DIV(ISP_DOUT_PCLK_ISP_133, "dout_pclk_isp_133", "mout_kfc",
@@ -832,7 +832,7 @@ struct samsung_div_clock isp_div_clks[] __initdata = {
 	DIV(ISP_DOUT_SCLK_MPWM, "dout_sclk_mpwm", "mout_kfc", DIV_ISP, 20, 2),
 };
 
-struct samsung_gate_clock isp_gate_clks[] __initdata = {
+static struct samsung_gate_clock isp_gate_clks[] __initdata = {
 	GATE(ISP_CLK_GIC, "clk_isp_gic", "mout_aclk_isp1_266",
 			EN_IP_ISP0, 15, 0, 0),
 
@@ -934,13 +934,13 @@ static unsigned long kfc_clk_regs[] __initdata = {
 PNAME(mout_kfc_pll_p) = {"fin_pll", "fout_kfc_pll"};
 PNAME(mout_kfc_p)	 = {"mout_kfc_pll", "dout_media_pll"};
 
-struct samsung_mux_clock kfc_mux_clks[] __initdata = {
+static struct samsung_mux_clock kfc_mux_clks[] __initdata = {
 	MUX(KFC_MOUT_KFC_PLL, "mout_kfc_pll", mout_kfc_pll_p,
 			MUX_SEL_KFC0, 0, 1),
 	MUX(KFC_MOUT_KFC, "mout_kfc", mout_kfc_p, MUX_SEL_KFC2, 0, 1),
 };
 
-struct samsung_div_clock kfc_div_clks[] __initdata = {
+static struct samsung_div_clock kfc_div_clks[] __initdata = {
 	DIV(KFC_DOUT_KFC1, "dout_kfc1", "mout_kfc", DIV_KFC, 0, 3),
 	DIV(KFC_DOUT_KFC2, "dout_kfc2", "dout_kfc1", DIV_KFC, 4, 3),
 	DIV(KFC_DOUT_KFC_ATCLK, "dout_kfc_atclk", "dout_kfc2", DIV_KFC, 8, 3),
@@ -993,18 +993,18 @@ static unsigned long mfc_clk_regs[] __initdata = {
 
 PNAME(mout_aclk_mfc_333_user_p) = {"fin_pll", "dout_aclk_mfc_333"};
 
-struct samsung_mux_clock mfc_mux_clks[] __initdata = {
+static struct samsung_mux_clock mfc_mux_clks[] __initdata = {
 	MUX(MFC_MOUT_ACLK_MFC_333_USER, "mout_aclk_mfc_333_user",
 			mout_aclk_mfc_333_user_p,
 			MUX_SEL_MFC, 0, 1),
 };
 
-struct samsung_div_clock mfc_div_clks[] __initdata = {
+static struct samsung_div_clock mfc_div_clks[] __initdata = {
 	DIV(MFC_DOUT_PCLK_MFC_83, "dout_pclk_mfc_83", "mout_aclk_mfc_333_user",
 			DIV_MFC, 0, 3),
 };
 
-struct samsung_gate_clock mfc_gate_clks[] __initdata = {
+static struct samsung_gate_clock mfc_gate_clks[] __initdata = {
 	GATE(MFC_CLK_MFC, "clk_mfc", "mout_aclk_mfc_333_user",
 			EN_IP_MFC, 1, 0, 0),
 	GATE(MFC_CLK_SMMU2_MFCM0, "clk_smmu2_mfcm0", "mout_aclk_mfc_333_user",
@@ -1078,7 +1078,7 @@ PNAME(mout_mif_drex2x_p) = {"dout_mem_pll", "dout_bus_pll"};
 PNAME(mout_clkm_phy_p) = {"mout_mif_drex", "dout_media_pll"};
 PNAME(mout_clk2x_phy_p) = {"mout_mif_drex2x", "dout_media_pll"};
 
-struct samsung_mux_clock mif_mux_clks[] __initdata = {
+static struct samsung_mux_clock mif_mux_clks[] __initdata = {
 	MUX(MIF_MOUT_MEM_PLL, "mout_mem_pll", mout_mem_pll_p,
 			MUX_SEL_MIF, 0, 1),
 	MUX(MIF_MOUT_BUS_PLL, "mout_bus_pll", mout_bus_pll_p,
@@ -1095,7 +1095,7 @@ struct samsung_mux_clock mif_mux_clks[] __initdata = {
 			MUX_SEL_MIF, 24, 1),
 };
 
-struct samsung_div_clock mif_div_clks[] __initdata = {
+static struct samsung_div_clock mif_div_clks[] __initdata = {
 	DIV(MIF_DOUT_MEDIA_PLL, "dout_media_pll", "mout_media_pll",
 			DIV_MIF, 0, 3),
 	DIV(MIF_DOUT_MEM_PLL, "dout_mem_pll", "mout_mem_pll",
@@ -1114,7 +1114,7 @@ struct samsung_div_clock mif_div_clks[] __initdata = {
 			DIV_MIF, 28, 4),
 };
 
-struct samsung_gate_clock mif_gate_clks[] __initdata = {
+static struct samsung_gate_clock mif_gate_clks[] __initdata = {
 	GATE(MIF_CLK_LPDDR3PHY_WRAP0, "clk_lpddr3phy_wrap0", "dout_clk2x_phy",
 			EN_IP_MIF, 12, CLK_IGNORE_UNUSED, 0),
 	GATE(MIF_CLK_LPDDR3PHY_WRAP1, "clk_lpddr3phy_wrap1", "dout_clk2x_phy",
@@ -1221,7 +1221,7 @@ PNAME(mout_sclk_i2scod_p) = {"ioclk_i2s_cdclk", "fin_pll", "dout_aclk_peri_aud",
 PNAME(mout_sclk_spdif_p) = {"ioclk_spdif_extclk", "fin_pll",
 			"dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"};
 
-struct samsung_mux_clock peri_mux_clks[] __initdata = {
+static struct samsung_mux_clock peri_mux_clks[] __initdata = {
 	MUX(PERI_MOUT_SCLK_PCM, "mout_sclk_pcm", mout_sclk_pcm_p,
 			MUX_SEL_PERI1, 4, 2),
 	MUX(PERI_MOUT_SCLK_I2SCOD, "mout_sclk_i2scod", mout_sclk_i2scod_p,
@@ -1230,12 +1230,12 @@ struct samsung_mux_clock peri_mux_clks[] __initdata = {
 			MUX_SEL_PERI1, 20, 2),
 };
 
-struct samsung_div_clock peri_div_clks[] __initdata = {
+static struct samsung_div_clock peri_div_clks[] __initdata = {
 	DIV(PERI_DOUT_PCM, "dout_pcm", "mout_sclk_pcm", DIV_PERI, 0, 8),
 	DIV(PERI_DOUT_I2S, "dout_i2s", "mout_sclk_i2scod", DIV_PERI, 8, 6),
 };
 
-struct samsung_gate_clock peri_gate_clks[] __initdata = {
+static struct samsung_gate_clock peri_gate_clks[] __initdata = {
 	GATE(PERI_SCLK_PCM1, "sclk_pcm1", "dout_pcm", EN_SCLK_PERI, 0,
 			CLK_SET_RATE_PARENT, 0),
 	GATE(PERI_SCLK_I2S, "sclk_i2s", "dout_i2s", EN_SCLK_PERI, 1,
@@ -1432,7 +1432,7 @@ static unsigned long top_clk_regs[] __initdata = {
 };
 
 /* fixed rate clocks generated inside the soc */
-struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = {
+static struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = {
 	FRATE(PHYCLK_DPTX_PHY_CH3_TXD_CLK, "phyclk_dptx_phy_ch3_txd_clk", NULL,
 			CLK_IS_ROOT, 270000000),
 	FRATE(PHYCLK_DPTX_PHY_CH2_TXD_CLK, "phyclk_dptx_phy_ch2_txd_clk", NULL,
@@ -1519,7 +1519,7 @@ PNAME(mout_sclk_fsys_mmc1_sdclkin_b_p) = {"mout_sclk_fsys_mmc1_sdclkin_a",
 PNAME(mout_sclk_fsys_mmc2_sdclkin_b_p) = {"mout_sclk_fsys_mmc2_sdclkin_a",
 			"mout_mediatop_pll_user"};
 
-struct samsung_mux_clock top_mux_clks[] __initdata = {
+static struct samsung_mux_clock top_mux_clks[] __initdata = {
 	MUX(TOP_MOUT_MEDIATOP_PLL_USER, "mout_mediatop_pll_user",
 			mout_mediatop_pll_user_p,
 			MUX_SEL_TOP_PLL0, 0, 1),
@@ -1679,7 +1679,7 @@ struct samsung_mux_clock top_mux_clks[] __initdata = {
 			MUX_SEL_TOP_GSCL, 20, 1),
 };
 
-struct samsung_div_clock top_div_clks[] __initdata = {
+static struct samsung_div_clock top_div_clks[] __initdata = {
 	DIV(TOP_DOUT_ACLK_G2D_333, "dout_aclk_g2d_333", "mout_aclk_g2d_333",
 			DIV_TOP_G2D_MFC, 0, 3),
 	DIV(TOP_DOUT_ACLK_MFC_333, "dout_aclk_mfc_333", "mout_aclk_mfc_333",
@@ -1800,7 +1800,7 @@ struct samsung_div_clock top_div_clks[] __initdata = {
 
 };
 
-struct samsung_gate_clock top_gate_clks[] __initdata = {
+static struct samsung_gate_clock top_gate_clks[] __initdata = {
 	GATE(TOP_SCLK_MMC0, "sclk_fsys_mmc0_sdclkin",
 			"dout_sclk_fsys_mmc0_sdclkin_b",
 			EN_SCLK_TOP, 7, CLK_SET_RATE_PARENT, 0),
diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
index 07d666cc6a29..af9979001b95 100644
--- a/drivers/clk/samsung/clk-exynos5420.c
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -503,7 +503,7 @@ static struct samsung_fixed_factor_clock
 	FFACTOR(0, "ff_dout_spll2", "mout_sclk_spll", 1, 2, 0),
 };
 
-struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
 	MUX(0, "mout_aclk400_isp", mout_group3_5800_p, SRC_TOP0, 0, 3),
 	MUX(0, "mout_aclk400_mscl", mout_group3_5800_p, SRC_TOP0, 4, 3),
 	MUX(0, "mout_aclk400_wcore", mout_group2_5800_p, SRC_TOP0, 16, 3),
@@ -552,7 +552,7 @@ struct samsung_mux_clock exynos5800_mux_clks[] __initdata = {
 	MUX(0, "mout_fimd1", mout_group2_p, SRC_DISP10, 4, 3),
 };
 
-struct samsung_div_clock exynos5800_div_clks[] __initdata = {
+static struct samsung_div_clock exynos5800_div_clks[] __initdata = {
 	DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore", DIV_TOP0, 16, 3),
 
 	DIV(0, "dout_aclk550_cam", "mout_aclk550_cam",
@@ -568,14 +568,14 @@ struct samsung_div_clock exynos5800_div_clks[] __initdata = {
 	DIV(0, "dout_sclk_sw", "sclk_spll", DIV_TOP9, 24, 6),
 };
 
-struct samsung_gate_clock exynos5800_gate_clks[] __initdata = {
+static struct samsung_gate_clock exynos5800_gate_clks[] __initdata = {
 	GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam",
 				GATE_BUS_TOP, 24, 0, 0),
 	GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
 				GATE_BUS_TOP, 27, 0, 0),
 };
 
-struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
+static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
 	MUX(0, "sclk_bpll", mout_bpll_p, TOP_SPARE2, 0, 1),
 	MUX(0, "mout_aclk400_wcore_bpll", mout_aclk400_wcore_bpll_p,
 				TOP_SPARE2, 4, 1),
@@ -605,7 +605,7 @@ struct samsung_mux_clock exynos5420_mux_clks[] __initdata = {
 	MUX(0, "mout_fimd1", mout_group3_p, SRC_DISP10, 4, 1),
 };
 
-struct samsung_div_clock exynos5420_div_clks[] __initdata = {
+static struct samsung_div_clock exynos5420_div_clks[] __initdata = {
 	DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore_bpll",
 			DIV_TOP0, 16, 3),
 };

From f3db6f16bdfda536c15aefd4d47515231b3009f4 Mon Sep 17 00:00:00 2001
From: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Date: Tue, 28 Apr 2015 13:46:20 +0900
Subject: [PATCH 018/135] clk: cdce706: Constify parent names in clock init
 data

The array of parent names can be made as array of const pointers to
const strings.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-cdce706.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk-cdce706.c b/drivers/clk/clk-cdce706.c
index b8e4f8a822e9..8a2dfd0012f3 100644
--- a/drivers/clk/clk-cdce706.c
+++ b/drivers/clk/clk-cdce706.c
@@ -94,7 +94,7 @@ static const char * const cdce706_source_name[] = {
 	"clk_in0", "clk_in1",
 };
 
-static const char *cdce706_clkin_name[] = {
+static const char * const cdce706_clkin_name[] = {
 	"clk_in",
 };
 
@@ -102,7 +102,7 @@ static const char * const cdce706_pll_name[] = {
 	"pll1", "pll2", "pll3",
 };
 
-static const char *cdce706_divider_parent_name[] = {
+static const char * const cdce706_divider_parent_name[] = {
 	"clk_in", "pll1", "pll2", "pll2", "pll3",
 };
 

From 45195b8f8402bcb8e519b2b2c8521d47c6c5d96c Mon Sep 17 00:00:00 2001
From: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Date: Tue, 28 Apr 2015 13:46:21 +0900
Subject: [PATCH 019/135] clk: sirf: Constify parent names in clock init data

The array of parent names can be made as array of const pointers to
const strings.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/sirf/clk-common.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/sirf/clk-common.c b/drivers/clk/sirf/clk-common.c
index 37af51c5f213..e9cf5730effe 100644
--- a/drivers/clk/sirf/clk-common.c
+++ b/drivers/clk/sirf/clk-common.c
@@ -188,7 +188,7 @@ static struct clk_ops std_pll_ops = {
 	.set_rate = pll_clk_set_rate,
 };
 
-static const char *pll_clk_parents[] = {
+static const char * const pll_clk_parents[] = {
 	"osc",
 };
 
@@ -284,7 +284,7 @@ static struct clk_hw usb_pll_clk_hw = {
  * clock domains - cpu, mem, sys/io, dsp, gfx
  */
 
-static const char *dmn_clk_parents[] = {
+static const char * const dmn_clk_parents[] = {
 	"rtc",
 	"osc",
 	"pll1",
@@ -673,7 +673,7 @@ static void std_clk_disable(struct clk_hw *hw)
 	clkc_writel(val, reg);
 }
 
-static const char *std_clk_io_parents[] = {
+static const char * const std_clk_io_parents[] = {
 	"io",
 };
 
@@ -949,7 +949,7 @@ static struct clk_std clk_pulse = {
 	},
 };
 
-static const char *std_clk_dsp_parents[] = {
+static const char * const std_clk_dsp_parents[] = {
 	"dsp",
 };
 
@@ -981,7 +981,7 @@ static struct clk_std clk_mf = {
 	},
 };
 
-static const char *std_clk_sys_parents[] = {
+static const char * const std_clk_sys_parents[] = {
 	"sys",
 };
 
@@ -999,7 +999,7 @@ static struct clk_std clk_security = {
 	},
 };
 
-static const char *std_clk_usb_parents[] = {
+static const char * const std_clk_usb_parents[] = {
 	"usb_pll",
 };
 

From 2ad8b3fcf5b43f269ab463ff27c41f4637a4967f Mon Sep 17 00:00:00 2001
From: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Date: Tue, 28 Apr 2015 13:46:22 +0900
Subject: [PATCH 020/135] clk: ls1x: Fix duplicate const for parent names

Replace duplicated const keyword with proper array of const pointers to
const strings.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-ls1x.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk-ls1x.c b/drivers/clk/clk-ls1x.c
index ca80103ac188..d4c61985f448 100644
--- a/drivers/clk/clk-ls1x.c
+++ b/drivers/clk/clk-ls1x.c
@@ -80,9 +80,9 @@ static struct clk *__init clk_register_pll(struct device *dev,
 	return clk;
 }
 
-static const char const *cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", };
-static const char const *ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", };
-static const char const *dc_parents[] = { "dc_clk_div", "osc_33m_clk", };
+static const char * const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", };
+static const char * const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", };
+static const char * const dc_parents[] = { "dc_clk_div", "osc_33m_clk", };
 
 void __init ls1x_clk_init(void)
 {

From 1237dc44300c429c4dcfc81e038ee049dad883b1 Mon Sep 17 00:00:00 2001
From: Krzysztof Kozlowski <k.kozlowski.k@gmail.com>
Date: Sat, 2 May 2015 01:02:47 +0900
Subject: [PATCH 021/135] clk: s3c2410: Staticize local symbols

Staticize symbols not exported and not used outside of file.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski.k@gmail.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/samsung/clk-s3c2410-dclk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c
index f4f29ed6bd25..db6fddb211d4 100644
--- a/drivers/clk/samsung/clk-s3c2410-dclk.c
+++ b/drivers/clk/samsung/clk-s3c2410-dclk.c
@@ -81,13 +81,13 @@ static int s3c24xx_clkout_set_parent(struct clk_hw *hw, u8 index)
 	return ret;
 }
 
-const struct clk_ops s3c24xx_clkout_ops = {
+static const struct clk_ops s3c24xx_clkout_ops = {
 	.get_parent = s3c24xx_clkout_get_parent,
 	.set_parent = s3c24xx_clkout_set_parent,
 	.determine_rate = __clk_mux_determine_rate,
 };
 
-struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
+static struct clk *s3c24xx_register_clkout(struct device *dev, const char *name,
 		const char **parent_names, u8 num_parents,
 		u8 shift, u32 mask)
 {

From d5255ec362f67586392c368fd21c8a2746e84e77 Mon Sep 17 00:00:00 2001
From: Krzysztof Kozlowski <k.kozlowski.k@gmail.com>
Date: Sat, 2 May 2015 01:02:48 +0900
Subject: [PATCH 022/135] clk: s3c2410: Constify platform_device_id

The platform_device_id is not modified by the driver and core uses it as
const.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski.k@gmail.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/samsung/clk-s3c2410-dclk.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c
index db6fddb211d4..e56df5064889 100644
--- a/drivers/clk/samsung/clk-s3c2410-dclk.c
+++ b/drivers/clk/samsung/clk-s3c2410-dclk.c
@@ -404,7 +404,7 @@ static struct s3c24xx_dclk_drv_data dclk_variants[] = {
 	},
 };
 
-static struct platform_device_id s3c24xx_dclk_driver_ids[] = {
+static const struct platform_device_id s3c24xx_dclk_driver_ids[] = {
 	{
 		.name		= "s3c2410-dclk",
 		.driver_data	= (kernel_ulong_t)&dclk_variants[S3C2410],

From 70e9f4dde00182600989ca57f08d51be12f1523f Mon Sep 17 00:00:00 2001
From: Felipe Balbi <balbi@ti.com>
Date: Fri, 1 May 2015 09:48:37 -0500
Subject: [PATCH 023/135] clk: add newline character after dumping all clocks

clk_dump() will dump data about all clocks in JSON
format, but it misses a newline character at the
end of the JSON string. This patch adds that missing
newline character.

Signed-off-by: Felipe Balbi <balbi@ti.com>
[sboyd@codeaurora.org: Squelch checkpatch with seq_puts()]
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index ea7e8695a32b..4a2e9478edbd 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1998,7 +1998,7 @@ static int clk_dump(struct seq_file *s, void *data)
 
 	clk_prepare_unlock();
 
-	seq_printf(s, "}");
+	seq_puts(s, "}\n");
 	return 0;
 }
 

From a6ae41b54cb077270456acdf090c9db1663c75b5 Mon Sep 17 00:00:00 2001
From: Linus Walleij <linus.walleij@linaro.org>
Date: Mon, 20 Apr 2015 15:06:28 +0200
Subject: [PATCH 024/135] clk: ux500: ape[ate|trace]clk are scaleable

The APEATCLK and APETRACECLK are actually scaleable so register
them as scaleable clocks.

Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/ux500/u8500_clk.c    | 7 ++++---
 drivers/clk/ux500/u8500_of_clk.c | 4 ++--
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c
index 80069c370a47..4626b97b7d83 100644
--- a/drivers/clk/ux500/u8500_clk.c
+++ b/drivers/clk/ux500/u8500_clk.c
@@ -116,11 +116,12 @@ void u8500_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
 	clk_register_clkdev(clk, NULL, "hdmi");
 	clk_register_clkdev(clk, "hdmi", "mcde");
 
-	clk = clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, CLK_IS_ROOT);
+	clk = clk_reg_prcmu_scalable("apeatclk", NULL, PRCMU_APEATCLK, 0,
+				     CLK_IS_ROOT|CLK_SET_RATE_GATE);
 	clk_register_clkdev(clk, NULL, "apeat");
 
-	clk = clk_reg_prcmu_gate("apetraceclk", NULL, PRCMU_APETRACECLK,
-				CLK_IS_ROOT);
+	clk = clk_reg_prcmu_scalable("apetraceclk", NULL, PRCMU_APETRACECLK, 0,
+				CLK_IS_ROOT|CLK_SET_RATE_GATE);
 	clk_register_clkdev(clk, NULL, "apetrace");
 
 	clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT);
diff --git a/drivers/clk/ux500/u8500_of_clk.c b/drivers/clk/ux500/u8500_of_clk.c
index 7b55ef89baa5..e319ef912dc6 100644
--- a/drivers/clk/ux500/u8500_of_clk.c
+++ b/drivers/clk/ux500/u8500_of_clk.c
@@ -166,8 +166,8 @@ void u8500_of_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
 	clk = clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, CLK_IS_ROOT);
 	prcmu_clk[PRCMU_APEATCLK] = clk;
 
-	clk = clk_reg_prcmu_gate("apetraceclk", NULL, PRCMU_APETRACECLK,
-				CLK_IS_ROOT);
+	clk = clk_reg_prcmu_scalable("apetraceclk", NULL, PRCMU_APETRACECLK, 0,
+				CLK_IS_ROOT|CLK_SET_RATE_GATE);
 	prcmu_clk[PRCMU_APETRACECLK] = clk;
 
 	clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT);

From c542a54fcb5591e7637f71fa400065853ce54ee0 Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas@glider.be>
Date: Mon, 27 Apr 2015 14:51:33 +0200
Subject: [PATCH 025/135] clk: emev2: Use generic names for device nodes

uart -> serial

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 Documentation/devicetree/bindings/clock/emev2-clock.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/clock/emev2-clock.txt b/Documentation/devicetree/bindings/clock/emev2-clock.txt
index 60bbb1a8c69a..268ca615459e 100644
--- a/Documentation/devicetree/bindings/clock/emev2-clock.txt
+++ b/Documentation/devicetree/bindings/clock/emev2-clock.txt
@@ -52,7 +52,7 @@ usia_u0_sclk: usia_u0_sclk {
 
 Example of consumer:
 
-uart@e1020000 {
+serial@e1020000 {
 	compatible = "renesas,em-uart";
 	reg = <0xe1020000 0x38>;
 	interrupts = <0 8 0>;

From a63347251907d7f9fc2fc02e3b9898efda573c05 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Wed, 6 May 2015 17:00:54 -0700
Subject: [PATCH 026/135] clk: Add some more lockdep assertions

We don't check to make sure the enable_lock is held across
enable/disable and we don't check if the prepare_lock is held
across prepare/unprepare. Add some asserts to catch any future
locking problems.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 9e9d18cadeee..659f2b036cf5 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -543,6 +543,8 @@ EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest);
 
 static void clk_core_unprepare(struct clk_core *core)
 {
+	lockdep_assert_held(&prepare_lock);
+
 	if (!core)
 		return;
 
@@ -589,6 +591,8 @@ static int clk_core_prepare(struct clk_core *core)
 {
 	int ret = 0;
 
+	lockdep_assert_held(&prepare_lock);
+
 	if (!core)
 		return 0;
 
@@ -644,6 +648,8 @@ EXPORT_SYMBOL_GPL(clk_prepare);
 
 static void clk_core_disable(struct clk_core *core)
 {
+	lockdep_assert_held(&enable_lock);
+
 	if (!core)
 		return;
 
@@ -692,6 +698,8 @@ static int clk_core_enable(struct clk_core *core)
 {
 	int ret = 0;
 
+	lockdep_assert_held(&enable_lock);
+
 	if (!core)
 		return 0;
 

From c4b6c26e828f4df30fe3289f35c100088f2ff71d Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer@pengutronix.de>
Date: Thu, 7 May 2015 10:14:58 +0200
Subject: [PATCH 027/135] dt-bindings: ARM: Mediatek: use more generic node
 name in examples

Use 'clock-controller' and 'power-controller' as node names in the
examples rather than the specific names of the units.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 .../devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt    | 2 +-
 .../devicetree/bindings/arm/mediatek/mediatek,infracfg.txt      | 2 +-
 .../devicetree/bindings/arm/mediatek/mediatek,pericfg.txt       | 2 +-
 .../devicetree/bindings/arm/mediatek/mediatek,topckgen.txt      | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
index 5af6d7394608..936166fbee09 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
@@ -16,7 +16,7 @@ The available clocks are defined in dt-bindings/clock/mt*-clk.h.
 
 Example:
 
-apmixedsys: apmixedsys@10209000 {
+apmixedsys: clock-controller@10209000 {
 	compatible = "mediatek,mt8173-apmixedsys";
 	reg = <0 0x10209000 0 0x1000>;
 	#clock-cells = <1>;
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
index 684da473b3e8..f6cd3e4192ff 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
@@ -22,7 +22,7 @@ dt-bindings/reset-controller/mt*-resets.h
 
 Example:
 
-infracfg: infracfg@10001000 {
+infracfg: power-controller@10001000 {
 	compatible = "mediatek,mt8173-infracfg", "syscon";
 	reg = <0 0x10001000 0 0x1000>;
 	#clock-cells = <1>;
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
index fdb45c6b63de..f25b85499a6f 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt
@@ -22,7 +22,7 @@ dt-bindings/reset-controller/mt*-resets.h
 
 Example:
 
-pericfg: pericfg@10003000 {
+pericfg: power-controller@10003000 {
 	compatible = "mediatek,mt8173-pericfg", "syscon";
 	reg = <0 0x10003000 0 0x1000>;
 	#clock-cells = <1>;
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
index a4252489860d..f9e917994ced 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
@@ -16,7 +16,7 @@ The available clocks are defined in dt-bindings/clock/mt*-clk.h.
 
 Example:
 
-topckgen: topckgen@10000000 {
+topckgen: power-controller@10000000 {
 	compatible = "mediatek,mt8173-topckgen";
 	reg = <0 0x10000000 0 0x1000>;
 	#clock-cells = <1>;

From 42c86547f4e5c2e81616c76ce9a2badce515c41f Mon Sep 17 00:00:00 2001
From: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Date: Wed, 11 Mar 2015 11:34:25 +0100
Subject: [PATCH 028/135] clk: Expose clk_hw_reparent() to providers

To be used by clock implementations for switching to a new parent during
rate change.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/clk/clk.c            | 8 ++++++++
 include/linux/clk-provider.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 459ce9da13e0..5315a273eae9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2020,6 +2020,14 @@ static void clk_core_reparent(struct clk_core *clk,
 	__clk_recalc_rates(clk, POST_RATE_CHANGE);
 }
 
+void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent)
+{
+	if (!hw)
+		return;
+
+	clk_core_reparent(hw->core, !new_parent ? NULL : new_parent->core);
+}
+
 /**
  * clk_has_parent - check if a clock is a possible parent for another
  * @clk: clock source
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index df695313f975..51efb9ec3e37 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -589,6 +589,7 @@ long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
 			      unsigned long max_rate,
 			      unsigned long *best_parent_rate,
 			      struct clk_hw **best_parent_p);
+void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent);
 
 static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src)
 {

From e34812c5bac8de641a2551b5ccb601627c10e772 Mon Sep 17 00:00:00 2001
From: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Date: Thu, 12 Mar 2015 15:47:56 +0100
Subject: [PATCH 029/135] of: document new emc-timings subnode in
 nvidia,tegra124-car

The EMC clock needs some extra information for changing its rate.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 .../bindings/clock/nvidia,tegra124-car.txt    | 42 ++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt
index c6620bc96703..c3891cece73f 100644
--- a/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt
@@ -21,10 +21,31 @@ Required properties :
   In clock consumers, this cell represents the bit number in the CAR's
   array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
 
+The node should contain a "emc-timings" subnode for each supported RAM type (see
+field RAM_CODE in register PMC_STRAPPING_OPT_A).
+
+Required properties for "emc-timings" nodes :
+- nvidia,ram-code : Should contain the value of RAM_CODE this timing set
+  is used for.
+
+Each "emc-timings" node should contain a "timing" subnode for every supported
+EMC clock rate.
+
+Required properties for "timing" nodes :
+- clock-frequency : Should contain the memory clock rate to which this timing
+relates.
+- nvidia,parent-clock-frequency : Should contain the rate at which the current
+parent of the EMC clock should be running at this timing.
+- clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names : Must include the following entries:
+  - emc-parent : the clock that should be the parent of the EMC clock at this
+timing.
+
 Example SoC include file:
 
 / {
-	tegra_car: clock {
+	tegra_car: clock@60006000 {
 		compatible = "nvidia,tegra124-car";
 		reg = <0x60006000 0x1000>;
 		#clock-cells = <1>;
@@ -62,4 +83,23 @@ Example board file:
 	&tegra_car {
 		clocks = <&clk_32k> <&osc>;
 	};
+
+	clock@60006000 {
+		emc-timings-3 {
+			nvidia,ram-code = <3>;
+
+			timing-12750000 {
+				clock-frequency = <12750000>;
+				nvidia,parent-clock-frequency = <408000000>;
+				clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+				clock-names = "emc-parent";
+			};
+			timing-20400000 {
+				clock-frequency = <20400000>;
+				nvidia,parent-clock-frequency = <408000000>;
+				clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
+				clock-names = "emc-parent";
+			};
+		};
+	};
 };

From ef03b35a9a2cadd6b3abc758dab4c580a454760c Mon Sep 17 00:00:00 2001
From: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Date: Thu, 12 Mar 2015 15:47:59 +0100
Subject: [PATCH 030/135] of: document external-memory-controller property in
 tegra124-car

This property contains a phandle to the EMC driver that is needed by the
EMC clock to request the EMC driver to do its part of the clock change
sequence.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt
index c3891cece73f..7f02fb4ca4ad 100644
--- a/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.txt
@@ -20,6 +20,7 @@ Required properties :
 - #reset-cells : Should be 1.
   In clock consumers, this cell represents the bit number in the CAR's
   array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
+- nvidia,external-memory-controller : phandle of the EMC driver.
 
 The node should contain a "emc-timings" subnode for each supported RAM type (see
 field RAM_CODE in register PMC_STRAPPING_OPT_A).
@@ -50,6 +51,7 @@ Example SoC include file:
 		reg = <0x60006000 0x1000>;
 		#clock-cells = <1>;
 		#reset-cells = <1>;
+		nvidia,external-memory-controller = <&emc>;
 	};
 
 	usb@c5004000 {

From 374ffadaf3abd4bf77073bd8f1acf0ada7dc797e Mon Sep 17 00:00:00 2001
From: Mikko Perttunen <mperttunen@nvidia.com>
Date: Thu, 12 Mar 2015 15:47:53 +0100
Subject: [PATCH 031/135] clk: tegra: Remove old Tegra124 EMC clock

This clock has never been able to do anything.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/clk/tegra/clk-tegra124.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index 11f857cd5f6a..62fe3cf7fcb5 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -791,7 +791,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
 	[tegra_clk_i2c2] = { .dt_id = TEGRA124_CLK_I2C2, .present = true },
 	[tegra_clk_uartc] = { .dt_id = TEGRA124_CLK_UARTC, .present = true },
 	[tegra_clk_mipi_cal] = { .dt_id = TEGRA124_CLK_MIPI_CAL, .present = true },
-	[tegra_clk_emc] = { .dt_id = TEGRA124_CLK_EMC, .present = true },
 	[tegra_clk_usb2] = { .dt_id = TEGRA124_CLK_USB2, .present = true },
 	[tegra_clk_usb3] = { .dt_id = TEGRA124_CLK_USB3, .present = true },
 	[tegra_clk_vde_8] = { .dt_id = TEGRA124_CLK_VDE, .present = true },

From 2db04f16b589c6c96bd07df3f1ef8558bfdb6810 Mon Sep 17 00:00:00 2001
From: Mikko Perttunen <mperttunen@nvidia.com>
Date: Thu, 12 Mar 2015 15:48:05 +0100
Subject: [PATCH 032/135] clk: tegra: Add EMC clock driver

The driver is currently only tested on Tegra124 Jetson TK1, but should
work with other Tegra124 boards, provided that correct EMC tables are
provided through the device tree. Older chip models have differing
timing change sequences, so they are not currently supported.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
[treding@nvidia.com: use more consistent function names]
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/clk/tegra/Makefile       |   2 +-
 drivers/clk/tegra/clk-emc.c      | 527 +++++++++++++++++++++++++++++++
 drivers/clk/tegra/clk-tegra124.c |   5 +-
 drivers/clk/tegra/clk.h          |   3 +
 4 files changed, 535 insertions(+), 2 deletions(-)
 create mode 100644 drivers/clk/tegra/clk-emc.c

diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index edb8358fa6ce..18c28d1ae400 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -14,5 +14,5 @@ obj-y					+= clk-tegra-super-gen4.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clk-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)         += clk-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= clk-tegra114.o
-obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= clk-tegra124.o
+obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= clk-tegra124.o clk-emc.o
 obj-$(CONFIG_ARCH_TEGRA_132_SOC)	+= clk-tegra124.o
diff --git a/drivers/clk/tegra/clk-emc.c b/drivers/clk/tegra/clk-emc.c
new file mode 100644
index 000000000000..32e5563711ac
--- /dev/null
+++ b/drivers/clk/tegra/clk-emc.c
@@ -0,0 +1,527 @@
+/*
+ * drivers/clk/tegra/clk-emc.c
+ *
+ * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * Author:
+ *	Mikko Perttunen <mperttunen@nvidia.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/sort.h>
+#include <linux/string.h>
+
+#include <soc/tegra/fuse.h>
+#include <soc/tegra/emc.h>
+
+#include "clk.h"
+
+#define CLK_SOURCE_EMC 0x19c
+
+#define CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_SHIFT 0
+#define CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_MASK 0xff
+#define CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR(x) (((x) & CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_MASK) << \
+					      CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_SHIFT)
+
+#define CLK_SOURCE_EMC_EMC_2X_CLK_SRC_SHIFT 29
+#define CLK_SOURCE_EMC_EMC_2X_CLK_SRC_MASK 0x7
+#define CLK_SOURCE_EMC_EMC_2X_CLK_SRC(x) (((x) & CLK_SOURCE_EMC_EMC_2X_CLK_SRC_MASK) << \
+					  CLK_SOURCE_EMC_EMC_2X_CLK_SRC_SHIFT)
+
+static const char * const emc_parent_clk_names[] = {
+	"pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud",
+	"pll_c2", "pll_c3", "pll_c_ud"
+};
+
+/*
+ * List of clock sources for various parents the EMC clock can have.
+ * When we change the timing to a timing with a parent that has the same
+ * clock source as the current parent, we must first change to a backup
+ * timing that has a different clock source.
+ */
+
+#define EMC_SRC_PLL_M 0
+#define EMC_SRC_PLL_C 1
+#define EMC_SRC_PLL_P 2
+#define EMC_SRC_CLK_M 3
+#define EMC_SRC_PLL_C2 4
+#define EMC_SRC_PLL_C3 5
+
+static const char emc_parent_clk_sources[] = {
+	EMC_SRC_PLL_M, EMC_SRC_PLL_C, EMC_SRC_PLL_P, EMC_SRC_CLK_M,
+	EMC_SRC_PLL_M, EMC_SRC_PLL_C2, EMC_SRC_PLL_C3, EMC_SRC_PLL_C
+};
+
+struct emc_timing {
+	unsigned long rate, parent_rate;
+	u8 parent_index;
+	struct clk *parent;
+	u32 ram_code;
+};
+
+struct tegra_clk_emc {
+	struct clk_hw hw;
+	void __iomem *clk_regs;
+	struct clk *prev_parent;
+	bool changing_timing;
+
+	struct device_node *emc_node;
+	struct tegra_emc *emc;
+
+	int num_timings;
+	struct emc_timing *timings;
+	spinlock_t *lock;
+};
+
+/* Common clock framework callback implementations */
+
+static unsigned long emc_recalc_rate(struct clk_hw *hw,
+				     unsigned long parent_rate)
+{
+	struct tegra_clk_emc *tegra;
+	u32 val, div;
+
+	tegra = container_of(hw, struct tegra_clk_emc, hw);
+
+	/*
+	 * CCF wrongly assumes that the parent won't change during set_rate,
+	 * so get the parent rate explicitly.
+	 */
+	parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
+
+	val = readl(tegra->clk_regs + CLK_SOURCE_EMC);
+	div = val & CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR_MASK;
+
+	return parent_rate / (div + 2) * 2;
+}
+
+/*
+ * Rounds up unless no higher rate exists, in which case down. This way is
+ * safer since things have EMC rate floors. Also don't touch parent_rate
+ * since we don't want the CCF to play with our parent clocks.
+ */
+static long emc_round_rate(struct clk_hw *hw, unsigned long rate,
+		    unsigned long *parent_rate)
+{
+	struct tegra_clk_emc *tegra;
+	u8 ram_code = tegra_read_ram_code();
+	struct emc_timing *timing = NULL;
+	int i;
+
+	tegra = container_of(hw, struct tegra_clk_emc, hw);
+
+         for (i = 0; i < tegra->num_timings; i++) {
+                if (tegra->timings[i].ram_code != ram_code)
+                        continue;
+
+                timing = tegra->timings + i;
+
+                if (timing->rate >= rate)
+                        return timing->rate;
+        }
+
+        if (timing)
+                return timing->rate;
+
+	return __clk_get_rate(hw->clk);
+}
+
+static u8 emc_get_parent(struct clk_hw *hw)
+{
+	struct tegra_clk_emc *tegra;
+	u32 val;
+
+	tegra = container_of(hw, struct tegra_clk_emc, hw);
+
+	val = readl(tegra->clk_regs + CLK_SOURCE_EMC);
+
+	return (val >> CLK_SOURCE_EMC_EMC_2X_CLK_SRC_SHIFT)
+		& CLK_SOURCE_EMC_EMC_2X_CLK_SRC_MASK;
+}
+
+static struct tegra_emc *emc_ensure_emc_driver(struct tegra_clk_emc *tegra)
+{
+	struct platform_device *pdev;
+
+	if (tegra->emc)
+		return tegra->emc;
+
+	if (!tegra->emc_node)
+		return NULL;
+
+	pdev = of_find_device_by_node(tegra->emc_node);
+	if (!pdev) {
+		pr_err("%s: could not get external memory controller\n",
+		       __func__);
+		return NULL;
+	}
+
+	of_node_put(tegra->emc_node);
+	tegra->emc_node = NULL;
+
+	tegra->emc = platform_get_drvdata(pdev);
+	if (!tegra->emc) {
+		pr_err("%s: cannot find EMC driver\n", __func__);
+		return NULL;
+	}
+
+	return tegra->emc;
+}
+
+static int emc_set_timing(struct tegra_clk_emc *tegra,
+			  struct emc_timing *timing)
+{
+	int err;
+	u8 div;
+	u32 car_value;
+	unsigned long flags = 0;
+	struct tegra_emc *emc = emc_ensure_emc_driver(tegra);
+
+	if (!emc)
+		return -ENOENT;
+
+	pr_debug("going to rate %ld prate %ld p %s\n", timing->rate,
+		 timing->parent_rate, __clk_get_name(timing->parent));
+
+	if (emc_get_parent(&tegra->hw) == timing->parent_index &&
+	    clk_get_rate(timing->parent) != timing->parent_rate) {
+		BUG();
+		return -EINVAL;
+	}
+
+	tegra->changing_timing = true;
+
+	err = clk_set_rate(timing->parent, timing->parent_rate);
+	if (err) {
+		pr_err("cannot change parent %s rate to %ld: %d\n",
+		       __clk_get_name(timing->parent), timing->parent_rate,
+		       err);
+
+		return err;
+	}
+
+	err = clk_prepare_enable(timing->parent);
+	if (err) {
+		pr_err("cannot enable parent clock: %d\n", err);
+		return err;
+	}
+
+	div = timing->parent_rate / (timing->rate / 2) - 2;
+
+	err = tegra_emc_prepare_timing_change(emc, timing->rate);
+	if (err)
+		return err;
+
+	spin_lock_irqsave(tegra->lock, flags);
+
+	car_value = readl(tegra->clk_regs + CLK_SOURCE_EMC);
+
+	car_value &= ~CLK_SOURCE_EMC_EMC_2X_CLK_SRC(~0);
+	car_value |= CLK_SOURCE_EMC_EMC_2X_CLK_SRC(timing->parent_index);
+
+	car_value &= ~CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR(~0);
+	car_value |= CLK_SOURCE_EMC_EMC_2X_CLK_DIVISOR(div);
+
+	writel(car_value, tegra->clk_regs + CLK_SOURCE_EMC);
+
+	spin_unlock_irqrestore(tegra->lock, flags);
+
+	tegra_emc_complete_timing_change(emc, timing->rate);
+
+	clk_hw_reparent(&tegra->hw, __clk_get_hw(timing->parent));
+	clk_disable_unprepare(tegra->prev_parent);
+
+	tegra->prev_parent = timing->parent;
+	tegra->changing_timing = false;
+
+	return 0;
+}
+
+/*
+ * Get backup timing to use as an intermediate step when a change between
+ * two timings with the same clock source has been requested. First try to
+ * find a timing with a higher clock rate to avoid a rate below any set rate
+ * floors. If that is not possible, find a lower rate.
+ */
+static struct emc_timing *get_backup_timing(struct tegra_clk_emc *tegra,
+					    int timing_index)
+{
+	int i;
+	u32 ram_code = tegra_read_ram_code();
+	struct emc_timing *timing;
+
+	for (i = timing_index+1; i < tegra->num_timings; i++) {
+		timing = tegra->timings + i;
+		if (timing->ram_code != ram_code)
+			continue;
+
+		if (emc_parent_clk_sources[timing->parent_index] !=
+		    emc_parent_clk_sources[
+		      tegra->timings[timing_index].parent_index])
+			return timing;
+	}
+
+	for (i = timing_index-1; i >= 0; --i) {
+		timing = tegra->timings + i;
+		if (timing->ram_code != ram_code)
+			continue;
+
+		if (emc_parent_clk_sources[timing->parent_index] !=
+		    emc_parent_clk_sources[
+		      tegra->timings[timing_index].parent_index])
+			return timing;
+	}
+
+	return NULL;
+}
+
+static int emc_set_rate(struct clk_hw *hw, unsigned long rate,
+			unsigned long parent_rate)
+{
+	struct tegra_clk_emc *tegra;
+	struct emc_timing *timing = NULL;
+	int i, err;
+	u32 ram_code = tegra_read_ram_code();
+
+	tegra = container_of(hw, struct tegra_clk_emc, hw);
+
+	if (__clk_get_rate(hw->clk) == rate)
+		return 0;
+
+	/*
+	 * When emc_set_timing changes the parent rate, CCF will propagate
+	 * that downward to us, so ignore any set_rate calls while a rate
+	 * change is already going on.
+	 */
+	if (tegra->changing_timing)
+		return 0;
+
+	for (i = 0; i < tegra->num_timings; i++) {
+		if (tegra->timings[i].rate == rate &&
+		    tegra->timings[i].ram_code == ram_code) {
+			timing = tegra->timings + i;
+			break;
+		}
+	}
+
+	if (!timing) {
+		pr_err("cannot switch to rate %ld without emc table\n", rate);
+		return -EINVAL;
+	}
+
+	if (emc_parent_clk_sources[emc_get_parent(hw)] ==
+	    emc_parent_clk_sources[timing->parent_index] &&
+	    clk_get_rate(timing->parent) != timing->parent_rate) {
+		/*
+		 * Parent clock source not changed but parent rate has changed,
+		 * need to temporarily switch to another parent
+		 */
+
+		struct emc_timing *backup_timing;
+
+		backup_timing = get_backup_timing(tegra, i);
+		if (!backup_timing) {
+			pr_err("cannot find backup timing\n");
+			return -EINVAL;
+		}
+
+		pr_debug("using %ld as backup rate when going to %ld\n",
+			 backup_timing->rate, rate);
+
+		err = emc_set_timing(tegra, backup_timing);
+		if (err) {
+			pr_err("cannot set backup timing: %d\n", err);
+			return err;
+		}
+	}
+
+	return emc_set_timing(tegra, timing);
+}
+
+/* Initialization and deinitialization */
+
+static int load_one_timing_from_dt(struct tegra_clk_emc *tegra,
+				   struct emc_timing *timing,
+				   struct device_node *node)
+{
+	int err, i;
+	u32 tmp;
+
+	err = of_property_read_u32(node, "clock-frequency", &tmp);
+	if (err) {
+		pr_err("timing %s: failed to read rate\n", node->full_name);
+		return err;
+	}
+
+	timing->rate = tmp;
+
+	err = of_property_read_u32(node, "nvidia,parent-clock-frequency", &tmp);
+	if (err) {
+		pr_err("timing %s: failed to read parent rate\n",
+		       node->full_name);
+		return err;
+	}
+
+	timing->parent_rate = tmp;
+
+	timing->parent = of_clk_get_by_name(node, "emc-parent");
+	if (IS_ERR(timing->parent)) {
+		pr_err("timing %s: failed to get parent clock\n",
+		       node->full_name);
+		return PTR_ERR(timing->parent);
+	}
+
+	timing->parent_index = 0xff;
+	for (i = 0; i < ARRAY_SIZE(emc_parent_clk_names); i++) {
+		if (!strcmp(emc_parent_clk_names[i],
+			    __clk_get_name(timing->parent))) {
+			timing->parent_index = i;
+			break;
+		}
+	}
+	if (timing->parent_index == 0xff) {
+		pr_err("timing %s: %s is not a valid parent\n",
+		       node->full_name, __clk_get_name(timing->parent));
+		clk_put(timing->parent);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int cmp_timings(const void *_a, const void *_b)
+{
+	const struct emc_timing *a = _a;
+	const struct emc_timing *b = _b;
+
+	if (a->rate < b->rate)
+		return -1;
+	else if (a->rate == b->rate)
+		return 0;
+	else
+		return 1;
+}
+
+static int load_timings_from_dt(struct tegra_clk_emc *tegra,
+				struct device_node *node,
+				u32 ram_code)
+{
+	struct device_node *child;
+	int child_count = of_get_child_count(node);
+	int i = 0, err;
+
+	tegra->timings = kcalloc(child_count, sizeof(struct emc_timing),
+				 GFP_KERNEL);
+	if (!tegra->timings)
+		return -ENOMEM;
+
+	tegra->num_timings = child_count;
+
+	for_each_child_of_node(node, child) {
+		struct emc_timing *timing = tegra->timings + (i++);
+
+		err = load_one_timing_from_dt(tegra, timing, child);
+		if (err)
+			return err;
+
+		timing->ram_code = ram_code;
+	}
+
+	sort(tegra->timings, tegra->num_timings, sizeof(struct emc_timing),
+	     cmp_timings, NULL);
+
+	return 0;
+}
+
+static const struct clk_ops tegra_clk_emc_ops = {
+	.recalc_rate = emc_recalc_rate,
+	.round_rate = emc_round_rate,
+	.set_rate = emc_set_rate,
+	.get_parent = emc_get_parent,
+};
+
+struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
+				   spinlock_t *lock)
+{
+	struct tegra_clk_emc *tegra;
+	struct clk_init_data init;
+	struct device_node *node;
+	u32 node_ram_code;
+	struct clk *clk;
+	int err;
+
+	tegra = kcalloc(1, sizeof(*tegra), GFP_KERNEL);
+	if (!tegra)
+		return ERR_PTR(-ENOMEM);
+
+	tegra->clk_regs = base;
+	tegra->lock = lock;
+
+	tegra->num_timings = 0;
+
+	for_each_child_of_node(np, node) {
+		err = of_property_read_u32(node, "nvidia,ram-code",
+					   &node_ram_code);
+		if (err) {
+			of_node_put(node);
+			continue;
+		}
+
+		/*
+		 * Store timings for all ram codes as we cannot read the
+		 * fuses until the apbmisc driver is loaded.
+		 */
+		err = load_timings_from_dt(tegra, node, node_ram_code);
+		if (err)
+			return ERR_PTR(err);
+		of_node_put(node);
+		break;
+	}
+
+	if (tegra->num_timings == 0)
+		pr_warn("%s: no memory timings registered\n", __func__);
+
+	tegra->emc_node = of_parse_phandle(np,
+			"nvidia,external-memory-controller", 0);
+	if (!tegra->emc_node)
+		pr_warn("%s: couldn't find node for EMC driver\n", __func__);
+
+	init.name = "emc";
+	init.ops = &tegra_clk_emc_ops;
+	init.flags = 0;
+	init.parent_names = emc_parent_clk_names;
+	init.num_parents = ARRAY_SIZE(emc_parent_clk_names);
+
+	tegra->hw.init = &init;
+
+	clk = clk_register(NULL, &tegra->hw);
+	if (IS_ERR(clk))
+		return clk;
+
+	tegra->prev_parent = clk_get_parent_by_index(
+		tegra->hw.clk, emc_get_parent(&tegra->hw));
+	tegra->changing_timing = false;
+
+	/* Allow debugging tools to see the EMC clock */
+	clk_register_clkdev(clk, "emc", "tegra-clk-debug");
+
+	clk_prepare_enable(clk);
+
+	return clk;
+};
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index 62fe3cf7fcb5..096261d0a44e 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -1388,7 +1388,6 @@ static struct tegra_clk_init_table common_init_table[] __initdata = {
 	{TEGRA124_CLK_XUSB_HOST_SRC, TEGRA124_CLK_PLL_RE_OUT, 112000000, 0},
 	{TEGRA124_CLK_SATA, TEGRA124_CLK_PLL_P, 104000000, 0},
 	{TEGRA124_CLK_SATA_OOB, TEGRA124_CLK_PLL_P, 204000000, 0},
-	{TEGRA124_CLK_EMC, TEGRA124_CLK_CLK_MAX, 0, 1},
 	{TEGRA124_CLK_MSELECT, TEGRA124_CLK_CLK_MAX, 0, 1},
 	{TEGRA124_CLK_CSITE, TEGRA124_CLK_CLK_MAX, 0, 1},
 	{TEGRA124_CLK_TSENSOR, TEGRA124_CLK_CLK_M, 400000, 0},
@@ -1512,6 +1511,10 @@ static void __init tegra124_132_clock_init_post(struct device_node *np)
 	tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks,
 				  &pll_x_params);
 	tegra_add_of_provider(np);
+
+	clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np,
+							&emc_lock);
+
 	tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
 
 	tegra_cpu_car_ops = &tegra124_cpu_car_ops;
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index d6ac00647faf..e69e98a7bc80 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -623,6 +623,9 @@ void tegra_super_clk_gen4_init(void __iomem *clk_base,
 			void __iomem *pmc_base, struct tegra_clk *tegra_clks,
 			struct tegra_clk_pll_params *pll_params);
 
+struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
+				   spinlock_t *lock);
+
 void tegra114_clock_tune_cpu_trimmers_high(void);
 void tegra114_clock_tune_cpu_trimmers_low(void);
 void tegra114_clock_tune_cpu_trimmers_init(void);

From ac67477f8f4163a6e7678f252030051f4eef2d5f Mon Sep 17 00:00:00 2001
From: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Date: Thu, 12 Mar 2015 15:48:07 +0100
Subject: [PATCH 033/135] clk: tegra: Set the EMC clock as the parent of the MC
 clock

On Tegra124, as we now have a proper driver for the EMC.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/clk/tegra/clk-tegra124.c | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index 096261d0a44e..e8cca3eac007 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -152,11 +152,6 @@ static unsigned long tegra124_input_freq[] = {
 	[12] = 260000000,
 };
 
-static const char *mux_pllmcp_clkm[] = {
-	"pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_c2", "pll_c3",
-};
-#define mux_pllmcp_clkm_idx NULL
-
 static struct div_nmp pllxc_nmp = {
 	.divm_shift = 0,
 	.divm_width = 8,
@@ -1126,13 +1121,7 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base,
 					     periph_clk_enb_refcnt);
 	clks[TEGRA124_CLK_DSIB] = clk;
 
-	/* emc mux */
-	clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
-			       ARRAY_SIZE(mux_pllmcp_clkm), 0,
-			       clk_base + CLK_SOURCE_EMC,
-			       29, 3, 0, &emc_lock);
-
-	clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
+	clk = tegra_clk_register_mc("mc", "emc", clk_base + CLK_SOURCE_EMC,
 				    &emc_lock);
 	clks[TEGRA124_CLK_MC] = clk;
 

From 890d6a54ead9dafdfdeebe65cbb10056e14c835a Mon Sep 17 00:00:00 2001
From: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Date: Tue, 17 Mar 2015 10:36:13 +0100
Subject: [PATCH 034/135] clk: tegra: Have EMC clock implement determine_rate()

As opposed to round_rate(), determine_rate() can take rate constraints
into account when choosing the best rate.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/clk/tegra/clk-emc.c | 35 +++++++++++++++++++++++------------
 1 file changed, 23 insertions(+), 12 deletions(-)

diff --git a/drivers/clk/tegra/clk-emc.c b/drivers/clk/tegra/clk-emc.c
index 32e5563711ac..7649685c86bc 100644
--- a/drivers/clk/tegra/clk-emc.c
+++ b/drivers/clk/tegra/clk-emc.c
@@ -116,8 +116,11 @@ static unsigned long emc_recalc_rate(struct clk_hw *hw,
  * safer since things have EMC rate floors. Also don't touch parent_rate
  * since we don't want the CCF to play with our parent clocks.
  */
-static long emc_round_rate(struct clk_hw *hw, unsigned long rate,
-		    unsigned long *parent_rate)
+static long emc_determine_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long min_rate,
+			       unsigned long max_rate,
+			       unsigned long *best_parent_rate,
+			       struct clk_hw **best_parent_hw)
 {
 	struct tegra_clk_emc *tegra;
 	u8 ram_code = tegra_read_ram_code();
@@ -126,18 +129,26 @@ static long emc_round_rate(struct clk_hw *hw, unsigned long rate,
 
 	tegra = container_of(hw, struct tegra_clk_emc, hw);
 
-         for (i = 0; i < tegra->num_timings; i++) {
-                if (tegra->timings[i].ram_code != ram_code)
-                        continue;
+	for (i = 0; i < tegra->num_timings; i++) {
+		if (tegra->timings[i].ram_code != ram_code)
+			continue;
 
-                timing = tegra->timings + i;
+		timing = tegra->timings + i;
 
-                if (timing->rate >= rate)
-                        return timing->rate;
-        }
+		if (timing->rate > max_rate) {
+			i = min(i, 1);
+			return tegra->timings[i - 1].rate;
+		}
 
-        if (timing)
-                return timing->rate;
+		if (timing->rate < min_rate)
+			continue;
+
+		if (timing->rate >= rate)
+			return timing->rate;
+	}
+
+	if (timing)
+		return timing->rate;
 
 	return __clk_get_rate(hw->clk);
 }
@@ -451,7 +462,7 @@ static int load_timings_from_dt(struct tegra_clk_emc *tegra,
 
 static const struct clk_ops tegra_clk_emc_ops = {
 	.recalc_rate = emc_recalc_rate,
-	.round_rate = emc_round_rate,
+	.determine_rate = emc_determine_rate,
 	.set_rate = emc_set_rate,
 	.get_parent = emc_get_parent,
 };

From 31b52ba42d71e9ed8ee544e64c340ec6c571272f Mon Sep 17 00:00:00 2001
From: Thierry Reding <treding@nvidia.com>
Date: Wed, 1 Apr 2015 09:10:58 +0200
Subject: [PATCH 035/135] clk: tegra: EMC clock driver depends on EMC driver

The EMC clock driver uses symbols exported by the EMC driver, so it
needs the corresponding dependency to avoid build breakage.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/clk/Kconfig        | 1 +
 drivers/clk/tegra/Kconfig  | 3 +++
 drivers/clk/tegra/Makefile | 3 ++-
 drivers/clk/tegra/clk.h    | 9 +++++++++
 4 files changed, 15 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/tegra/Kconfig

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 9897f353bf1a..ff20c485418a 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -158,3 +158,4 @@ source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/mvebu/Kconfig"
 
 source "drivers/clk/samsung/Kconfig"
+source "drivers/clk/tegra/Kconfig"
diff --git a/drivers/clk/tegra/Kconfig b/drivers/clk/tegra/Kconfig
new file mode 100644
index 000000000000..1ba30d1e14f2
--- /dev/null
+++ b/drivers/clk/tegra/Kconfig
@@ -0,0 +1,3 @@
+config TEGRA_CLK_EMC
+	def_bool y
+	depends on TEGRA124_EMC
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index 18c28d1ae400..aec862ba7a17 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -11,8 +11,9 @@ obj-y					+= clk-tegra-periph.o
 obj-y					+= clk-tegra-pmc.o
 obj-y					+= clk-tegra-fixed.o
 obj-y					+= clk-tegra-super-gen4.o
+obj-$(CONFIG_TEGRA_CLK_EMC)		+= clk-emc.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clk-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)         += clk-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= clk-tegra114.o
-obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= clk-tegra124.o clk-emc.o
+obj-$(CONFIG_ARCH_TEGRA_124_SOC)	+= clk-tegra124.o
 obj-$(CONFIG_ARCH_TEGRA_132_SOC)	+= clk-tegra124.o
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index e69e98a7bc80..75ddc8ff8bd4 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -623,8 +623,17 @@ void tegra_super_clk_gen4_init(void __iomem *clk_base,
 			void __iomem *pmc_base, struct tegra_clk *tegra_clks,
 			struct tegra_clk_pll_params *pll_params);
 
+#ifdef CONFIG_TEGRA_CLK_EMC
 struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
 				   spinlock_t *lock);
+#else
+static inline struct clk *tegra_clk_register_emc(void __iomem *base,
+						 struct device_node *np,
+						 spinlock_t *lock)
+{
+	return NULL;
+}
+#endif
 
 void tegra114_clock_tune_cpu_trimmers_high(void);
 void tegra114_clock_tune_cpu_trimmers_low(void);

From 36b7be6d3ea8f434f1e0723f3fb0e85c3e00ebc2 Mon Sep 17 00:00:00 2001
From: Marcel Ziswiler <marcel.ziswiler@toradex.com>
Date: Fri, 10 Apr 2015 23:35:57 +0200
Subject: [PATCH 036/135] clk: tegra: Fix hda2codec_2x clock name for Tegra30

The HDA to codec clock is named hda2codec_2x, so use the proper name in
the clock table.

Signed-off-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/clk/tegra/clk-tegra30.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index 4b26509fc218..0af3e834dd24 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -679,7 +679,7 @@ static struct tegra_devclk devclks[] __initdata = {
 	{ .dev_id = "tegra30-dam.1", .dt_id = TEGRA30_CLK_DAM1 },
 	{ .dev_id = "tegra30-dam.2", .dt_id = TEGRA30_CLK_DAM2 },
 	{ .con_id = "hda", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA },
-	{ .con_id = "hda2codec", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA2CODEC_2X },
+	{ .con_id = "hda2codec_2x", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA2CODEC_2X },
 	{ .dev_id = "spi_tegra.0", .dt_id = TEGRA30_CLK_SBC1 },
 	{ .dev_id = "spi_tegra.1", .dt_id = TEGRA30_CLK_SBC2 },
 	{ .dev_id = "spi_tegra.2", .dt_id = TEGRA30_CLK_SBC3 },

From 2073b5e909b96f8fbc9b8a40b89c1fa316fb092c Mon Sep 17 00:00:00 2001
From: Sergej Sawazki <ce3a@gmx.de>
Date: Mon, 11 May 2015 10:44:50 +0200
Subject: [PATCH 037/135] clk: si5351: fix .round_rate for multisynth 6-7

The divider calculation for multisynth 6 and 7 differs from the
calculation for multisynth 0-5.

For MS6 and MS7, set MSx_P1 directly, MSx_P1=divide value
[AN619, p. 6].

Referenced document:
[AN619] Manually Generating an Si5351 Register Map, Rev. 0.4

Signed-off-by: Sergej Sawazki <ce3a@gmx.de>
Signed-off-by: Michael Turquette <mturquette@linaro.org>
---
 drivers/clk/clk-si5351.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c
index 30335d3b99af..48c5298b6bb1 100644
--- a/drivers/clk/clk-si5351.c
+++ b/drivers/clk/clk-si5351.c
@@ -552,7 +552,8 @@ static const struct clk_ops si5351_pll_ops = {
  * MSx_P2[19:0] = 128 * b - c * floor(128 * b/c) = (128*b) mod c
  * MSx_P3[19:0] = c
  *
- * MS[6,7] are integer (P1) divide only, P2 = 0, P3 = 0
+ * MS[6,7] are integer (P1) divide only, P1 = divide value,
+ * P2 and P3 are not applicable
  *
  * for 150MHz < fOUT <= 160MHz:
  *
@@ -679,6 +680,16 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
 		c = 1;
 
 		*parent_rate = a * rate;
+	} else if (hwdata->num >= 6) {
+		/* determine the closest integer divider */
+		a = DIV_ROUND_CLOSEST(*parent_rate, rate);
+		if (a < SI5351_MULTISYNTH_A_MIN)
+			a = SI5351_MULTISYNTH_A_MIN;
+		if (a > SI5351_MULTISYNTH67_A_MAX)
+			a = SI5351_MULTISYNTH67_A_MAX;
+
+		b = 0;
+		c = 1;
 	} else {
 		unsigned long rfrac, denom;
 
@@ -692,9 +703,7 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
 		a = *parent_rate / rate;
 		if (a < SI5351_MULTISYNTH_A_MIN)
 			a = SI5351_MULTISYNTH_A_MIN;
-		if (hwdata->num >= 6 && a > SI5351_MULTISYNTH67_A_MAX)
-			a = SI5351_MULTISYNTH67_A_MAX;
-		else if (a > SI5351_MULTISYNTH_A_MAX)
+		if (a > SI5351_MULTISYNTH_A_MAX)
 			a = SI5351_MULTISYNTH_A_MAX;
 
 		/* find best approximation for b/c = fVCO mod fOUT */
@@ -723,6 +732,10 @@ static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate,
 		hwdata->params.p3 = 1;
 		hwdata->params.p2 = 0;
 		hwdata->params.p1 = 0;
+	} else if (hwdata->num >= 6) {
+		hwdata->params.p3 = 0;
+		hwdata->params.p2 = 0;
+		hwdata->params.p1 = a;
 	} else {
 		hwdata->params.p3  = c;
 		hwdata->params.p2  = (128 * b) % c;

From 45b03d3e88c2068644e377cf08fc480208700b85 Mon Sep 17 00:00:00 2001
From: Sergej Sawazki <ce3a@gmx.de>
Date: Mon, 11 May 2015 10:44:59 +0200
Subject: [PATCH 038/135] clk: si5351: fix .recalc_rate for multisynth 6-7

MS6 and MS7 do not have the MSx_P3 field. Do the 'params.p3 == 0'
check for MS0-M5 only. See [AN619, p. 6] for details.

Referenced document:
[AN619] Manually Generating an Si5351 Register Map, Rev. 0.4

Signed-off-by: Sergej Sawazki <ce3a@gmx.de>
Signed-off-by: Michael Turquette <mturquette@linaro.org>
---
 drivers/clk/clk-si5351.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c
index 48c5298b6bb1..e39e1e680b3c 100644
--- a/drivers/clk/clk-si5351.c
+++ b/drivers/clk/clk-si5351.c
@@ -607,9 +607,6 @@ static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw,
 	if (!hwdata->params.valid)
 		si5351_read_parameters(hwdata->drvdata, reg, &hwdata->params);
 
-	if (hwdata->params.p3 == 0)
-		return parent_rate;
-
 	/*
 	 * multisync0-5: fOUT = (128 * P3 * fIN) / (P1*P3 + P2 + 512*P3)
 	 * multisync6-7: fOUT = fIN / P1
@@ -617,6 +614,8 @@ static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw,
 	rate = parent_rate;
 	if (hwdata->num > 5) {
 		m = hwdata->params.p1;
+	} else if (hwdata->params.p3 == 0) {
+		return parent_rate;
 	} else if ((si5351_reg_read(hwdata->drvdata, reg + 2) &
 		    SI5351_OUTPUT_CLK_DIVBY4) == SI5351_OUTPUT_CLK_DIVBY4) {
 		m = 4;

From dbc3976d9123a00925e3c9893b3f40f58f82636c Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Thu, 7 May 2015 23:43:26 -0700
Subject: [PATCH 039/135] clk: bindings: Fix assigned-clock-rates description

The binding uses assigned-clock-parents when it should use
assigned-clock-rates. Furthermore, the part that describes how
they relate to the assigned-clocks property is not clear about
what is related. Correct and clarify this part of the binding.

Reported-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 Documentation/devicetree/bindings/clock/clock-bindings.txt | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
index 06fc6d541c89..2ec489eebe72 100644
--- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
+++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -138,9 +138,10 @@ Some platforms may require initial configuration of default parent clocks
 and clock frequencies. Such a configuration can be specified in a device tree
 node through assigned-clocks, assigned-clock-parents and assigned-clock-rates
 properties. The assigned-clock-parents property should contain a list of parent
-clocks in form of phandle and clock specifier pairs, the assigned-clock-parents
-property the list of assigned clock frequency values - corresponding to clocks
-listed in the assigned-clocks property.
+clocks in the form of a phandle and clock specifier pair and the
+assigned-clock-rates property should contain a list of frequencies in Hz. Both
+these properties should correspond to the clocks listed in the assigned-clocks
+property.
 
 To skip setting parent or rate of a clock its corresponding entry should be
 set to 0, or can be omitted if it is not followed by any non-zero entry.

From 42801ca46719b189d4090b76268e6db90fc01e3c Mon Sep 17 00:00:00 2001
From: Daniel Thompson <daniel.thompson@linaro.org>
Date: Mon, 11 May 2015 11:20:06 +0100
Subject: [PATCH 040/135] clk: Update docs after removal of clk-private.h

Currently Documentation/clk.txt describes an obsolete techinique to
statically define struct clk objects.

This capability was removed by b09d6d991025("clk: remove clk-private.h")
and is no longer supported. The documentation describing the feature should
be removed.

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Michael Turquette <mturquette@linaro.org>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 Documentation/clk.txt | 27 ++-------------------------
 1 file changed, 2 insertions(+), 25 deletions(-)

diff --git a/Documentation/clk.txt b/Documentation/clk.txt
index 0e4f90aa1c13..f463bdc37f88 100644
--- a/Documentation/clk.txt
+++ b/Documentation/clk.txt
@@ -230,30 +230,7 @@ clk_register(...)
 
 See the basic clock types in drivers/clk/clk-*.c for examples.
 
-	Part 5 - static initialization of clock data
-
-For platforms with many clocks (often numbering into the hundreds) it
-may be desirable to statically initialize some clock data.  This
-presents a problem since the definition of struct clk should be hidden
-from everyone except for the clock core in drivers/clk/clk.c.
-
-To get around this problem struct clk's definition is exposed in
-include/linux/clk-private.h along with some macros for more easily
-initializing instances of the basic clock types.  These clocks must
-still be initialized with the common clock framework via a call to
-__clk_init.
-
-clk-private.h must NEVER be included by code which implements struct
-clk_ops callbacks, nor must it be included by any logic which pokes
-around inside of struct clk at run-time.  To do so is a layering
-violation.
-
-To better enforce this policy, always follow this simple rule: any
-statically initialized clock data MUST be defined in a separate file
-from the logic that implements its ops.  Basically separate the logic
-from the data and all is well.
-
-	Part 6 - Disabling clock gating of unused clocks
+	Part 5 - Disabling clock gating of unused clocks
 
 Sometimes during development it can be useful to be able to bypass the
 default disabling of unused clocks. For example, if drivers aren't enabling
@@ -264,7 +241,7 @@ are sorted out.
 To bypass this disabling, include "clk_ignore_unused" in the bootargs to the
 kernel.
 
-	Part 7 - Locking
+	Part 6 - Locking
 
 The common clock framework uses two global locks, the prepare lock and the
 enable lock.

From b1ed311baf66d7e826f07f456b9f7945fa300aaf Mon Sep 17 00:00:00 2001
From: Maxime Ripard <maxime.ripard@free-electrons.com>
Date: Sat, 2 May 2015 17:03:21 +0200
Subject: [PATCH 041/135] clk: asm9260: Fix of_io_request_and_map error check

of_io_request_and map returns an error pointer, but the current code assumes
that on error the returned pointer will be NULL.

Obviously, that makes the check completely useless. Change the test to actually
check for the proper error code.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: linux-clk@vger.kernel.org
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-asm9260.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/clk-asm9260.c b/drivers/clk/clk-asm9260.c
index 88f4ff6916fe..90897af8d9f7 100644
--- a/drivers/clk/clk-asm9260.c
+++ b/drivers/clk/clk-asm9260.c
@@ -274,7 +274,7 @@ static void __init asm9260_acc_init(struct device_node *np)
 	u32 accuracy = 0;
 
 	base = of_io_request_and_map(np, 0, np->name);
-	if (!base)
+	if (IS_ERR(base))
 		panic("%s: unable to map resource", np->name);
 
 	/* register pll */

From beb7a2a97103ce31df639b35b6f3a07ca7f77188 Mon Sep 17 00:00:00 2001
From: Alexander Sverdlin <alexander.sverdlin@nokia.com>
Date: Wed, 13 May 2015 18:27:40 +0200
Subject: [PATCH 042/135] clk: axm55xx: Use %zu in pr_info for size_t

Fix the following compiler warning:

drivers/clk/clk-axm5516.c: In function 'axmclk_probe':
drivers/clk/clk-axm5516.c:559:2: warning: format '%u' expects argument of type 'unsigned int', but argument 2 has type 'size_t' [-Wformat=]
  pr_info("axmclk: supporting %u clocks\n", num_clks);
    ^

Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-axm5516.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/clk-axm5516.c b/drivers/clk/clk-axm5516.c
index 0f6368ceec4c..c7c91a5ecf8b 100644
--- a/drivers/clk/clk-axm5516.c
+++ b/drivers/clk/clk-axm5516.c
@@ -556,7 +556,7 @@ static int axmclk_probe(struct platform_device *pdev)
 		return PTR_ERR(regmap);
 
 	num_clks = ARRAY_SIZE(axmclk_clocks);
-	pr_info("axmclk: supporting %u clocks\n", num_clks);
+	pr_info("axmclk: supporting %zu clocks\n", num_clks);
 	priv = devm_kzalloc(dev, sizeof(*priv) + sizeof(*priv->clks) * num_clks,
 			    GFP_KERNEL);
 	if (!priv)

From e0cdcda508f110b7ec190dc7c5eb2869ba73a535 Mon Sep 17 00:00:00 2001
From: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Date: Wed, 13 May 2015 15:54:40 +0900
Subject: [PATCH 043/135] clk: ti: dra7-atl-clock: Fix possible ERR_PTR
 dereference

of_clk_get_from_provider() returns ERR_PTR on failure. The
dra7-atl-clock driver was not checking its return value and
immediately used it in __clk_get_hw().  __clk_get_hw()
dereferences supplied clock, if it is not NULL, so in that case
it would dereference an ERR_PTR.

Fixes: 9ac33b0ce81f ("CLK: TI: Driver for DRA7 ATL (Audio Tracking Logic)")
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/ti/clk-dra7-atl.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
index d86bc46b93bd..0a1df821860f 100644
--- a/drivers/clk/ti/clk-dra7-atl.c
+++ b/drivers/clk/ti/clk-dra7-atl.c
@@ -252,6 +252,11 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev)
 		}
 
 		clk = of_clk_get_from_provider(&clkspec);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to get atl clock %d from provider\n",
+			       __func__, i);
+			return PTR_ERR(clk);
+		}
 
 		cdesc = to_atl_desc(__clk_get_hw(clk));
 		cdesc->cinfo = cinfo;

From d122db7e86669244759226bfdd2b9d623d5c6ae8 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Thu, 14 May 2015 16:47:10 -0700
Subject: [PATCH 044/135] clk: basic-types: Remove useless allocation failure
 printks

Printing an error on kmalloc() failures is unnecessary. Remove
the print and use *ptr in sizeof() for future-proof code.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-composite.c          | 4 +---
 drivers/clk/clk-divider.c            | 6 ++----
 drivers/clk/clk-fixed-factor.c       | 4 +---
 drivers/clk/clk-fixed-rate.c         | 6 ++----
 drivers/clk/clk-fractional-divider.c | 4 +---
 drivers/clk/clk-gate.c               | 6 ++----
 6 files changed, 9 insertions(+), 21 deletions(-)

diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 077f4c7148f1..616f5aef3c26 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -200,10 +200,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
 	struct clk_ops *clk_composite_ops;
 
 	composite = kzalloc(sizeof(*composite), GFP_KERNEL);
-	if (!composite) {
-		pr_err("%s: could not allocate composite clk\n", __func__);
+	if (!composite)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	init.name = name;
 	init.flags = flags | CLK_IS_BASIC;
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 25006a8bb8e6..706b5783c360 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -430,11 +430,9 @@ static struct clk *_register_divider(struct device *dev, const char *name,
 	}
 
 	/* allocate the divider */
-	div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
-	if (!div) {
-		pr_err("%s: could not allocate divider clk\n", __func__);
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	init.name = name;
 	init.ops = &clk_divider_ops;
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index d9e3f671c2ea..e186db263d5e 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -74,10 +74,8 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
 	struct clk *clk;
 
 	fix = kmalloc(sizeof(*fix), GFP_KERNEL);
-	if (!fix) {
-		pr_err("%s: could not allocate fixed factor clk\n", __func__);
+	if (!fix)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	/* struct clk_fixed_factor assignments */
 	fix->mult = mult;
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
index 0fc56ab6e844..f85ec8d1711f 100644
--- a/drivers/clk/clk-fixed-rate.c
+++ b/drivers/clk/clk-fixed-rate.c
@@ -65,11 +65,9 @@ struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev,
 	struct clk_init_data init;
 
 	/* allocate fixed-rate clock */
-	fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
-	if (!fixed) {
-		pr_err("%s: could not allocate fixed clk\n", __func__);
+	fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
+	if (!fixed)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	init.name = name;
 	init.ops = &clk_fixed_rate_ops;
diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c
index 6aa72d9d79ba..140eb5844dc4 100644
--- a/drivers/clk/clk-fractional-divider.c
+++ b/drivers/clk/clk-fractional-divider.c
@@ -109,10 +109,8 @@ struct clk *clk_register_fractional_divider(struct device *dev,
 	struct clk *clk;
 
 	fd = kzalloc(sizeof(*fd), GFP_KERNEL);
-	if (!fd) {
-		dev_err(dev, "could not allocate fractional divider clk\n");
+	if (!fd)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	init.name = name;
 	init.ops = &clk_fractional_divider_ops;
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index 3f0e4200cb5d..551dd0672794 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -135,11 +135,9 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
 	}
 
 	/* allocate the gate */
-	gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
-	if (!gate) {
-		pr_err("%s: could not allocate gated clk\n", __func__);
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	init.name = name;
 	init.ops = &clk_gate_ops;

From 2bb5d1b88bb5c8dc929d3a24d5ad327c0281fdbf Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 12:14:24 -0700
Subject: [PATCH 045/135] clk: gpio-gate: Don't export __init functions

This function is marked as __init, so exposing it to modules
doesn't make any sense and it isn't used by modules anyway.

drivers/clk/clk-gpio-gate.c:192:13: warning: symbol 'of_gpio_gate_clk_setup' was not declared. Should it be static?

Cc: Jyri Sarha <jsarha@ti.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-gpio-gate.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/clk/clk-gpio-gate.c b/drivers/clk/clk-gpio-gate.c
index a71cabedda93..f564e624fb93 100644
--- a/drivers/clk/clk-gpio-gate.c
+++ b/drivers/clk/clk-gpio-gate.c
@@ -189,7 +189,7 @@ static struct clk *of_clk_gpio_gate_delayed_register_get(
 /**
  * of_gpio_gate_clk_setup() - Setup function for gpio controlled clock
  */
-void __init of_gpio_gate_clk_setup(struct device_node *node)
+static void __init of_gpio_gate_clk_setup(struct device_node *node)
 {
 	struct clk_gpio_gate_delayed_register_data *data;
 
@@ -203,6 +203,5 @@ void __init of_gpio_gate_clk_setup(struct device_node *node)
 
 	of_clk_add_provider(node, of_clk_gpio_gate_delayed_register_get, data);
 }
-EXPORT_SYMBOL_GPL(of_gpio_gate_clk_setup);
 CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup);
 #endif

From 562ef0b098552970fd25e9c960691e6c2bcb1181 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 12:16:14 -0700
Subject: [PATCH 046/135] clk: Silence sparse warnings about __clk_{get,put}()

drivers/clk/clk.c:2700:5: warning: symbol '__clk_get' was not declared. Should it be static?
drivers/clk/clk.c:2713:6: warning: symbol '__clk_put' was not declared. Should it be static?

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 659f2b036cf5..c44623fe9c48 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -21,6 +21,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/clkdev.h>
 
 #include "clk.h"
 

From 9a39222db60cca13c78effbff745801c7b3c17a9 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 12:17:37 -0700
Subject: [PATCH 047/135] clk: max-gen: Silence sparse warnings

drivers/clk/clk-max-gen.c:82:16: warning: symbol 'max_gen_clk_ops' was not declared. Should it be static?
drivers/clk/clk-max-gen.c:109:5: warning: symbol 'max_gen_clk_probe' was not declared. Should it be static?
drivers/clk/clk-max-gen.c:183:5: warning: symbol 'max_gen_clk_remove' was not declared. Should it be static?

Acked-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-max-gen.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/clk/clk-max-gen.c b/drivers/clk/clk-max-gen.c
index 6505049d50f1..35af9cb6da4f 100644
--- a/drivers/clk/clk-max-gen.c
+++ b/drivers/clk/clk-max-gen.c
@@ -31,6 +31,8 @@
 #include <linux/of.h>
 #include <linux/export.h>
 
+#include "clk-max-gen.h"
+
 struct max_gen_clk {
 	struct regmap *regmap;
 	u32 mask;

From 4cca1be4bca4b21657e2d99c43710dec14658673 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 12:21:53 -0700
Subject: [PATCH 048/135] clk: bcm/kona: Silence sparse warnings

drivers/clk/bcm/clk-kona.c:1243:16: warning: odd constant _Bool cast (ffffffffffffffea becomes 1)

Reviewed-by: Alex Elder <elder@linaro.org>
Cc: Tim Kryger <tim.kryger@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/bcm/clk-kona.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c
index a0ef4f75d457..79a98506c433 100644
--- a/drivers/clk/bcm/clk-kona.c
+++ b/drivers/clk/bcm/clk-kona.c
@@ -1240,7 +1240,7 @@ static bool __kona_clk_init(struct kona_clk *bcm_clk)
 	default:
 		BUG();
 	}
-	return -EINVAL;
+	return false;
 }
 
 /* Set a CCU and all its clocks into their desired initial state */

From 7926b3f8c62628f51a85bbc5fd806087d3fdfbac Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 12:23:08 -0700
Subject: [PATCH 049/135] clk: bcm/kona: Remove ccu_list

This list doesn't look to be used. Let's remove it and any
associated code that would be manipulating this list. This also
silences this error:

drivers/clk/bcm/clk-kona-setup.c:24:1: warning: symbol 'ccu_list' was not declared. Should it be static?

Reviewed-by: Alex Elder <elder@linaro.org>
Cc: Tim Kryger <tim.kryger@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/bcm/clk-kona-setup.c | 4 ----
 drivers/clk/bcm/clk-kona.h       | 2 --
 2 files changed, 6 deletions(-)

diff --git a/drivers/clk/bcm/clk-kona-setup.c b/drivers/clk/bcm/clk-kona-setup.c
index e5aededdd322..deaa7f962b84 100644
--- a/drivers/clk/bcm/clk-kona-setup.c
+++ b/drivers/clk/bcm/clk-kona-setup.c
@@ -21,8 +21,6 @@
 #define selector_clear_exists(sel)	((sel)->width = 0)
 #define trigger_clear_exists(trig)	FLAG_CLEAR(trig, TRIG, EXISTS)
 
-LIST_HEAD(ccu_list);	/* The list of set up CCUs */
-
 /* Validity checking */
 
 static bool ccu_data_offsets_valid(struct ccu_data *ccu)
@@ -773,7 +771,6 @@ static void kona_ccu_teardown(struct ccu_data *ccu)
 
 	of_clk_del_provider(ccu->node);	/* safe if never added */
 	ccu_clks_teardown(ccu);
-	list_del(&ccu->links);
 	of_node_put(ccu->node);
 	ccu->node = NULL;
 	iounmap(ccu->base);
@@ -847,7 +844,6 @@ void __init kona_dt_ccu_setup(struct ccu_data *ccu,
 		goto out_err;
 	}
 	ccu->node = of_node_get(node);
-	list_add_tail(&ccu->links, &ccu_list);
 
 	/*
 	 * Set up each defined kona clock and save the result in
diff --git a/drivers/clk/bcm/clk-kona.h b/drivers/clk/bcm/clk-kona.h
index 6849a64baf6d..906576ec97b6 100644
--- a/drivers/clk/bcm/clk-kona.h
+++ b/drivers/clk/bcm/clk-kona.h
@@ -480,7 +480,6 @@ struct ccu_data {
 	spinlock_t lock;	/* serialization lock */
 	bool write_enabled;	/* write access is currently enabled */
 	struct ccu_policy policy;
-	struct list_head links;	/* for ccu_list */
 	struct device_node *node;
 	struct clk_onecell_data clk_data;
 	const char *name;
@@ -492,7 +491,6 @@ struct ccu_data {
 #define KONA_CCU_COMMON(_prefix, _name, _ccuname)			    \
 	.name		= #_name "_ccu",				    \
 	.lock		= __SPIN_LOCK_UNLOCKED(_name ## _ccu_data.lock),    \
-	.links		= LIST_HEAD_INIT(_name ## _ccu_data.links),	    \
 	.clk_data	= {						    \
 		.clk_num = _prefix ## _ ## _ccuname ## _CCU_CLOCK_COUNT,    \
 	}

From 47c18e4cd99463241fb8dfd9ac37a59cc4b65c82 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 12:24:44 -0700
Subject: [PATCH 050/135] clk: berlin: Silence sparse warning

drivers/clk/berlin/berlin2-pll.c:94:12: warning: symbol 'berlin2_pll_register' was not declared. Should it be static?

Cc: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Acked-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/berlin/berlin2-pll.c | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/drivers/clk/berlin/berlin2-pll.c b/drivers/clk/berlin/berlin2-pll.c
index bdc506b03824..f4b8d324b083 100644
--- a/drivers/clk/berlin/berlin2-pll.c
+++ b/drivers/clk/berlin/berlin2-pll.c
@@ -25,14 +25,7 @@
 #include <asm/div64.h>
 
 #include "berlin2-div.h"
-
-struct berlin2_pll_map {
-	const u8 vcodiv[16];
-	u8 mult;
-	u8 fbdiv_shift;
-	u8 rfdiv_shift;
-	u8 divsel_shift;
-};
+#include "berlin2-pll.h"
 
 struct berlin2_pll {
 	struct clk_hw hw;

From 4a77f817b32031aa13992710dfd5c2ec4f3949be Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 12:25:53 -0700
Subject: [PATCH 051/135] clk: hix5hd2: Silence sparse warnings

drivers/clk/hisilicon/clk-hix5hd2.c:255:13: warning: symbol 'hix5hd2_clk_register_complex' was not declared. Should it be static?

Acked-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/hisilicon/clk-hix5hd2.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/hisilicon/clk-hix5hd2.c b/drivers/clk/hisilicon/clk-hix5hd2.c
index f1d239435826..78bd95b6fc7b 100644
--- a/drivers/clk/hisilicon/clk-hix5hd2.c
+++ b/drivers/clk/hisilicon/clk-hix5hd2.c
@@ -252,8 +252,9 @@ static struct clk_ops clk_complex_ops = {
 	.disable = clk_complex_disable,
 };
 
-void __init hix5hd2_clk_register_complex(struct hix5hd2_complex_clock *clks,
-					 int nums, struct hisi_clock_data *data)
+static void __init
+hix5hd2_clk_register_complex(struct hix5hd2_complex_clock *clks, int nums,
+			     struct hisi_clock_data *data)
 {
 	void __iomem *base = data->base;
 	int i;

From f6704f9e1995c862d5281fc9efc0b4e95ee9f9b9 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 12:32:17 -0700
Subject: [PATCH 052/135] clk: samsung: Silence sparse warnings

drivers/clk/samsung/clk-exynos5260.c:138:40: warning: Using plain integer as NULL pointer
drivers/clk/samsung/clk-exynos5260.c:328:40: warning: Using plain integer as NULL pointer
drivers/clk/samsung/clk-exynos5260.c:392:40: warning: Using plain integer as NULL pointer
drivers/clk/samsung/clk-exynos5260.c:494:40: warning: Using plain integer as NULL pointer
drivers/clk/samsung/clk-exynos5260.c:583:40: warning: Using plain integer as NULL pointer
drivers/clk/samsung/clk-exynos5260.c:644:40: warning: Using plain integer as NULL pointer
drivers/clk/samsung/clk-exynos5260.c:779:40: warning: Using plain integer as NULL pointer
drivers/clk/samsung/clk-exynos5260.c:898:40: warning: Using plain integer as NULL pointer
drivers/clk/samsung/clk-exynos5260.c:962:40: warning: Using plain integer as NULL pointer
drivers/clk/samsung/clk-exynos5260.c:1018:40: warning: Using plain integer as NULL pointer
drivers/clk/samsung/clk-exynos5260.c:1165:40: warning: Using plain integer as NULL pointer
drivers/clk/samsung/clk-exynos5260.c:1373:40: warning: Using plain integer as NULL pointer
drivers/clk/samsung/clk-exynos5260.c:1829:40: warning: Using plain integer as NULL pointer

Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/samsung/clk-exynos5260.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
index df1d83c45554..06f96eb7cf93 100644
--- a/drivers/clk/samsung/clk-exynos5260.c
+++ b/drivers/clk/samsung/clk-exynos5260.c
@@ -135,7 +135,7 @@ static struct samsung_gate_clock aud_gate_clks[] __initdata = {
 
 static void __init exynos5260_clk_aud_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = aud_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(aud_mux_clks);
@@ -325,7 +325,7 @@ static struct samsung_gate_clock disp_gate_clks[] __initdata = {
 
 static void __init exynos5260_clk_disp_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = disp_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(disp_mux_clks);
@@ -389,7 +389,7 @@ static struct samsung_pll_clock egl_pll_clks[] __initdata = {
 
 static void __init exynos5260_clk_egl_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.pll_clks = egl_pll_clks;
 	cmu.nr_pll_clks =  ARRAY_SIZE(egl_pll_clks);
@@ -491,7 +491,7 @@ static struct samsung_gate_clock fsys_gate_clks[] __initdata = {
 
 static void __init exynos5260_clk_fsys_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = fsys_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(fsys_mux_clks);
@@ -580,7 +580,7 @@ static struct samsung_gate_clock g2d_gate_clks[] __initdata = {
 
 static void __init exynos5260_clk_g2d_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = g2d_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(g2d_mux_clks);
@@ -641,7 +641,7 @@ static struct samsung_pll_clock g3d_pll_clks[] __initdata = {
 
 static void __init exynos5260_clk_g3d_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.pll_clks = g3d_pll_clks;
 	cmu.nr_pll_clks =  ARRAY_SIZE(g3d_pll_clks);
@@ -776,7 +776,7 @@ static struct samsung_gate_clock gscl_gate_clks[] __initdata = {
 
 static void __init exynos5260_clk_gscl_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = gscl_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(gscl_mux_clks);
@@ -895,7 +895,7 @@ static struct samsung_gate_clock isp_gate_clks[] __initdata = {
 
 static void __init exynos5260_clk_isp_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = isp_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(isp_mux_clks);
@@ -959,7 +959,7 @@ static struct samsung_pll_clock kfc_pll_clks[] __initdata = {
 
 static void __init exynos5260_clk_kfc_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.pll_clks = kfc_pll_clks;
 	cmu.nr_pll_clks =  ARRAY_SIZE(kfc_pll_clks);
@@ -1015,7 +1015,7 @@ static struct samsung_gate_clock mfc_gate_clks[] __initdata = {
 
 static void __init exynos5260_clk_mfc_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = mfc_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks);
@@ -1162,7 +1162,7 @@ static struct samsung_pll_clock mif_pll_clks[] __initdata = {
 
 static void __init exynos5260_clk_mif_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.pll_clks = mif_pll_clks;
 	cmu.nr_pll_clks =  ARRAY_SIZE(mif_pll_clks);
@@ -1370,7 +1370,7 @@ static struct samsung_gate_clock peri_gate_clks[] __initdata = {
 
 static void __init exynos5260_clk_peri_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.mux_clks = peri_mux_clks;
 	cmu.nr_mux_clks = ARRAY_SIZE(peri_mux_clks);
@@ -1826,7 +1826,7 @@ static struct samsung_pll_clock top_pll_clks[] __initdata = {
 
 static void __init exynos5260_clk_top_init(struct device_node *np)
 {
-	struct samsung_cmu_info cmu = {0};
+	struct samsung_cmu_info cmu = { NULL };
 
 	cmu.pll_clks = top_pll_clks;
 	cmu.nr_pll_clks =  ARRAY_SIZE(top_pll_clks);

From 43f535702bb2c7b96091c0267fc105d44c18348c Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 12:33:49 -0700
Subject: [PATCH 053/135] clk: emev2: Silence sparse warnings

drivers/clk/shmobile/clk-emev2.c:37:14: warning: symbol 'smu_base' was not declared. Should it be static?

Cc: Takashi Yoshii <takasi-y@ops.dti.ne.jp>
Cc: Magnus Damm <damm@opensource.se>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/shmobile/clk-emev2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/shmobile/clk-emev2.c b/drivers/clk/shmobile/clk-emev2.c
index 6c7c929c7765..5b60beb7d0eb 100644
--- a/drivers/clk/shmobile/clk-emev2.c
+++ b/drivers/clk/shmobile/clk-emev2.c
@@ -34,7 +34,7 @@
 static DEFINE_SPINLOCK(lock);
 
 /* not pretty, but hey */
-void __iomem *smu_base;
+static void __iomem *smu_base;
 
 static void __init emev2_smu_write(unsigned long value, int offs)
 {

From f53f551b11d112f6cdd6ab9ca320bfd890a9b021 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 12:36:24 -0700
Subject: [PATCH 054/135] clk: sirf: Silence sparse warnings

These are __iomem pointers. Mark them appropriately so we don't
get sparse errors like

drivers/clk/sirf/clk-common.c:60:16: warning: incorrect type in argument 1 (different address spaces)
drivers/clk/sirf/clk-common.c:60:16:    expected void const volatile [noderef] <asn:2>*addr
drivers/clk/sirf/clk-common.c:60:16:    got void *

Cc: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/sirf/clk-common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/sirf/clk-common.c b/drivers/clk/sirf/clk-common.c
index e9cf5730effe..9fc285d784d3 100644
--- a/drivers/clk/sirf/clk-common.c
+++ b/drivers/clk/sirf/clk-common.c
@@ -10,8 +10,8 @@
 #define KHZ     1000
 #define MHZ     (KHZ * KHZ)
 
-static void *sirfsoc_clk_vbase;
-static void *sirfsoc_rsc_vbase;
+static void __iomem *sirfsoc_clk_vbase;
+static void __iomem *sirfsoc_rsc_vbase;
 static struct clk_onecell_data clk_data;
 
 /*

From b011d386e9efdef6f5776435aad97a5bf302c041 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 12:39:52 -0700
Subject: [PATCH 055/135] clk: socfpga: Silence sparse warning

drivers/clk/socfpga/clk-gate.c:227:40: warning: Using plain integer as NULL pointer

Cc: Dinh Nguyen <dinguyen@altera.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/socfpga/clk-gate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c
index dd3a78c64795..0d5dc84372dc 100644
--- a/drivers/clk/socfpga/clk-gate.c
+++ b/drivers/clk/socfpga/clk-gate.c
@@ -224,7 +224,7 @@ static void __init __socfpga_gate_init(struct device_node *node,
 		socfpga_clk->shift = div_reg[1];
 		socfpga_clk->width = div_reg[2];
 	} else {
-		socfpga_clk->div_reg = 0;
+		socfpga_clk->div_reg = NULL;
 	}
 
 	rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2);

From 8e6dd77ccc324a57d5f37c7f8b1e37319fb2e2b3 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 12:45:53 -0700
Subject: [PATCH 056/135] clk: st: Silence sparse warnings

drivers/clk/st/clkgen-mux.c:134:4: warning: symbol 'clkgena_divmux_get_parent' was not declared. Should it be static?
drivers/clk/st/clkgen-mux.c:171:15: warning: symbol 'clkgena_divmux_recalc_rate' was not declared. Should it be static?
drivers/clk/st/clkgen-mux.c:218:12: warning: symbol 'clk_register_genamux' was not declared. Should it be static?
drivers/clk/st/clkgen-mux.c:388:13: warning: symbol 'st_of_clkgena_divmux_setup' was not declared. Should it be static?
drivers/clk/st/clkgen-mux.c:488:13: warning: symbol 'st_of_clkgena_prediv_setup' was not declared. Should it be static?
drivers/clk/st/clkgen-mux.c:625:13: warning: symbol 'st_of_clkgen_mux_setup' was not declared. Should it be static?
drivers/clk/st/clkgen-mux.c:702:13: warning: symbol 'st_of_clkgen_vcc_setup' was not declared. Should it be static?
drivers/clk/st/clkgen-pll.c:273:15: warning: symbol 'recalc_stm_pll800c65' was not declared. Should it be static?
drivers/clk/st/clkgen-pll.c:300:15: warning: symbol 'recalc_stm_pll1600c65' was not declared. Should it be static?
drivers/clk/st/clkgen-pll.c:324:15: warning: symbol 'recalc_stm_pll3200c32' was not declared. Should it be static?
drivers/clk/st/clkgen-pll.c:346:15: warning: symbol 'recalc_stm_pll1200c32' was not declared. Should it be static?
drivers/clk/st/clkgen-pll.c:565:19: warning: incorrect type in assignment (different address spaces)
drivers/clk/st/clkgen-pll.c:565:19:    expected void [noderef] <asn:2>*reg
drivers/clk/st/clkgen-pll.c:565:19:    got void *
drivers/clk/st/clkgen-pll.c:576:18: warning: incorrect type in assignment (different address spaces)
drivers/clk/st/clkgen-pll.c:576:18:    expected void [noderef] <asn:2>*reg
drivers/clk/st/clkgen-pll.c:576:18:    got void *
drivers/clk/st/clkgen-pll.c:693:53: warning: incorrect type in argument 2 (different address spaces)
drivers/clk/st/clkgen-pll.c:693:53:    expected void *[noderef] <asn:2>reg
drivers/clk/st/clkgen-pll.c:693:53:    got void [noderef] <asn:2>*[assigned] pll_base
drivers/clk/st/clkgen-fsyn.c:495:5: warning: symbol 'clk_fs660c32_vco_get_rate' was not declared. Should it be static?
drivers/clk/st/clkgen-fsyn.c:522:5: warning: symbol 'clk_fs660c32_vco_get_params' was not declared. Should it be static?
drivers/clk/st/clk-flexgen.c:119:15: warning: symbol 'flexgen_recalc_rate' was not declared. Should it be static?
drivers/clk/st/clk-flexgen.c:177:12: warning: symbol 'clk_register_flexgen' was not declared. Should it be static?
drivers/clk/st/clk-flexgen.c:263:13: warning: symbol 'st_of_flexgen_setup' was not declared. Should it be static?

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/st/clk-flexgen.c |  6 +++---
 drivers/clk/st/clkgen-fsyn.c |  4 ++--
 drivers/clk/st/clkgen-mux.c  | 14 +++++++-------
 drivers/clk/st/clkgen-pll.c  | 10 +++++-----
 4 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index bf12a25eb3a2..409ed4b0b569 100644
--- a/drivers/clk/st/clk-flexgen.c
+++ b/drivers/clk/st/clk-flexgen.c
@@ -116,7 +116,7 @@ static long flexgen_round_rate(struct clk_hw *hw, unsigned long rate,
 	return *prate / div;
 }
 
-unsigned long flexgen_recalc_rate(struct clk_hw *hw,
+static unsigned long flexgen_recalc_rate(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct flexgen *flexgen = to_flexgen(hw);
@@ -174,7 +174,7 @@ static const struct clk_ops flexgen_ops = {
 	.set_rate = flexgen_set_rate,
 };
 
-struct clk *clk_register_flexgen(const char *name,
+static struct clk *clk_register_flexgen(const char *name,
 				const char **parent_names, u8 num_parents,
 				void __iomem *reg, spinlock_t *lock, u32 idx,
 				unsigned long flexgen_flags) {
@@ -260,7 +260,7 @@ static const char ** __init flexgen_get_parents(struct device_node *np,
 	return parents;
 }
 
-void __init st_of_flexgen_setup(struct device_node *np)
+static void __init st_of_flexgen_setup(struct device_node *np)
 {
 	struct device_node *pnode;
 	void __iomem *reg;
diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c
index a917c4c7eaa9..e94197f04b0b 100644
--- a/drivers/clk/st/clkgen-fsyn.c
+++ b/drivers/clk/st/clkgen-fsyn.c
@@ -492,7 +492,7 @@ static int quadfs_pll_is_enabled(struct clk_hw *hw)
 	return !!npda;
 }
 
-int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs,
+static int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs,
 			   unsigned long *rate)
 {
 	unsigned long nd = fs->ndiv + 16; /* ndiv value */
@@ -519,7 +519,7 @@ static unsigned long quadfs_pll_fs660c32_recalc_rate(struct clk_hw *hw,
 	return rate;
 }
 
-int clk_fs660c32_vco_get_params(unsigned long input,
+static int clk_fs660c32_vco_get_params(unsigned long input,
 				unsigned long output, struct stm_fs *fs)
 {
 /* Formula
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index fdcff10f6d30..80aa77dbf660 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -131,7 +131,7 @@ static int clkgena_divmux_is_enabled(struct clk_hw *hw)
 	return (s8)clk_mux_ops.get_parent(mux_hw) > 0;
 }
 
-u8 clkgena_divmux_get_parent(struct clk_hw *hw)
+static u8 clkgena_divmux_get_parent(struct clk_hw *hw)
 {
 	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
 	struct clk_hw *mux_hw = &genamux->mux.hw;
@@ -168,7 +168,7 @@ static int clkgena_divmux_set_parent(struct clk_hw *hw, u8 index)
 	return 0;
 }
 
-unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw,
+static unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
@@ -215,7 +215,7 @@ static const struct clk_ops clkgena_divmux_ops = {
 /**
  * clk_register_genamux - register a genamux clock with the clock framework
  */
-struct clk *clk_register_genamux(const char *name,
+static struct clk *clk_register_genamux(const char *name,
 				const char **parent_names, u8 num_parents,
 				void __iomem *reg,
 				const struct clkgena_divmux_data *muxdata,
@@ -385,7 +385,7 @@ static void __iomem * __init clkgen_get_register_base(
 	return reg;
 }
 
-void __init st_of_clkgena_divmux_setup(struct device_node *np)
+static void __init st_of_clkgena_divmux_setup(struct device_node *np)
 {
 	const struct of_device_id *match;
 	const struct clkgena_divmux_data *data;
@@ -485,7 +485,7 @@ static const struct of_device_id clkgena_prediv_of_match[] = {
 	{}
 };
 
-void __init st_of_clkgena_prediv_setup(struct device_node *np)
+static void __init st_of_clkgena_prediv_setup(struct device_node *np)
 {
 	const struct of_device_id *match;
 	void __iomem *reg;
@@ -622,7 +622,7 @@ static const struct of_device_id mux_of_match[] = {
 	{}
 };
 
-void __init st_of_clkgen_mux_setup(struct device_node *np)
+static void __init st_of_clkgen_mux_setup(struct device_node *np)
 {
 	const struct of_device_id *match;
 	struct clk *clk;
@@ -699,7 +699,7 @@ static const struct of_device_id vcc_of_match[] = {
 	{}
 };
 
-void __init st_of_clkgen_vcc_setup(struct device_node *np)
+static void __init st_of_clkgen_vcc_setup(struct device_node *np)
 {
 	const struct of_device_id *match;
 	void __iomem *reg;
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
index d204ba85db3a..106532207213 100644
--- a/drivers/clk/st/clkgen-pll.c
+++ b/drivers/clk/st/clkgen-pll.c
@@ -270,7 +270,7 @@ static int clkgen_pll_is_enabled(struct clk_hw *hw)
 	return !poweroff;
 }
 
-unsigned long recalc_stm_pll800c65(struct clk_hw *hw,
+static unsigned long recalc_stm_pll800c65(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct clkgen_pll *pll = to_clkgen_pll(hw);
@@ -297,7 +297,7 @@ unsigned long recalc_stm_pll800c65(struct clk_hw *hw,
 
 }
 
-unsigned long recalc_stm_pll1600c65(struct clk_hw *hw,
+static unsigned long recalc_stm_pll1600c65(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct clkgen_pll *pll = to_clkgen_pll(hw);
@@ -321,7 +321,7 @@ unsigned long recalc_stm_pll1600c65(struct clk_hw *hw,
 	return rate;
 }
 
-unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
+static unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct clkgen_pll *pll = to_clkgen_pll(hw);
@@ -343,7 +343,7 @@ unsigned long recalc_stm_pll3200c32(struct clk_hw *hw,
 	return rate;
 }
 
-unsigned long recalc_stm_pll1200c32(struct clk_hw *hw,
+static unsigned long recalc_stm_pll1200c32(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct clkgen_pll *pll = to_clkgen_pll(hw);
@@ -544,7 +544,7 @@ CLK_OF_DECLARE(clkgena_c65_plls,
 	       "st,clkgena-plls-c65", clkgena_c65_pll_setup);
 
 static struct clk * __init clkgen_odf_register(const char *parent_name,
-					       void * __iomem reg,
+					       void __iomem *reg,
 					       struct clkgen_pll_data *pll_data,
 					       int odf,
 					       spinlock_t *odf_lock,

From 412d6b47cc6e33a04fe03be1db725202417f4d72 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 12:59:32 -0700
Subject: [PATCH 057/135] clk: ti: Silence sparse warnings

drivers/clk/ti/clk.c:125:31: warning: incorrect type in return expression (different address spaces)
drivers/clk/ti/clk.c:125:31:    expected void [noderef] <asn:2>*
drivers/clk/ti/clk.c:125:31:    got void *
drivers/clk/ti/clk.c:132:31: warning: incorrect type in return expression (different address spaces)
drivers/clk/ti/clk.c:132:31:    expected void [noderef] <asn:2>*
drivers/clk/ti/clk.c:132:31:    got void *
drivers/clk/ti/dpll.c:180:14: warning: symbol '_get_reg' was not declared. Should it be static?
drivers/clk/ti/fapll.c:624:32: warning: Using plain integer as NULL pointer
drivers/clk/ti/fapll.c:625:31: warning: Using plain integer as NULL pointer
drivers/clk/ti/fapll.c:630:40: warning: Using plain integer as NULL pointer
drivers/clk/ti/clk-dra7-atl.c:158:22: warning: symbol 'atl_clk_ops' was not declared. Should it be static?
drivers/clk/ti/clk-dra7-atl.c:170:39: warning: Using plain integer as NULL pointer

Acked-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Acked-by: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/ti/clk-dra7-atl.c | 4 ++--
 drivers/clk/ti/clk.c          | 4 ++--
 drivers/clk/ti/dpll.c         | 2 +-
 drivers/clk/ti/fapll.c        | 6 +++---
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
index 0a1df821860f..19e543a32e2b 100644
--- a/drivers/clk/ti/clk-dra7-atl.c
+++ b/drivers/clk/ti/clk-dra7-atl.c
@@ -155,7 +155,7 @@ static int atl_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 	return 0;
 }
 
-const struct clk_ops atl_clk_ops = {
+static const struct clk_ops atl_clk_ops = {
 	.enable		= atl_clk_enable,
 	.disable	= atl_clk_disable,
 	.is_enabled	= atl_clk_is_enabled,
@@ -167,7 +167,7 @@ const struct clk_ops atl_clk_ops = {
 static void __init of_dra7_atl_clock_setup(struct device_node *node)
 {
 	struct dra7_atl_desc *clk_hw = NULL;
-	struct clk_init_data init = { 0 };
+	struct clk_init_data init = { NULL };
 	const char **parent_names = NULL;
 	struct clk *clk;
 
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index 0ebe5c51062b..64bb5e8a3b8c 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -122,14 +122,14 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
 
 	if (i == CLK_MAX_MEMMAPS) {
 		pr_err("clk-provider not found for %s!\n", node->name);
-		return ERR_PTR(-ENOENT);
+		return IOMEM_ERR_PTR(-ENOENT);
 	}
 
 	reg->index = i;
 
 	if (of_property_read_u32_index(node, "reg", index, &val)) {
 		pr_err("%s must have reg[%d]!\n", node->name, index);
-		return ERR_PTR(-EINVAL);
+		return IOMEM_ERR_PTR(-EINVAL);
 	}
 
 	reg->offset = val;
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
index 11478a501c30..2aacf7a3bcae 100644
--- a/drivers/clk/ti/dpll.c
+++ b/drivers/clk/ti/dpll.c
@@ -177,7 +177,7 @@ cleanup:
 }
 
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS)
-void __iomem *_get_reg(u8 module, u16 offset)
+static void __iomem *_get_reg(u8 module, u16 offset)
 {
 	u32 reg;
 	struct clk_omap_reg *reg_setup;
diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c
index ffcd8e09e85b..730aa62454a2 100644
--- a/drivers/clk/ti/fapll.c
+++ b/drivers/clk/ti/fapll.c
@@ -621,13 +621,13 @@ static void __init ti_fapll_setup(struct device_node *node)
 
 		/* Check for hardwired audio_pll_clk1 */
 		if (is_audio_pll_clk1(freq)) {
-			freq = 0;
-			div = 0;
+			freq = NULL;
+			div = NULL;
 		} else {
 			/* Does the synthesizer have a FREQ register? */
 			v = readl_relaxed(freq);
 			if (!v)
-				freq = 0;
+				freq = NULL;
 		}
 		synth_clk = ti_fapll_synth_setup(fd, freq, div, output_instance,
 						 output_name, node->name,

From 11bee5e19afd11a42a03df9025f82a1bab4d5595 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 13:02:26 -0700
Subject: [PATCH 058/135] clk: versatile: Silence sparse warnings

drivers/clk/versatile/clk-sp810.c:159:29: error: incompatible types for operation (<=)
drivers/clk/versatile/clk-sp810.c:159:29:    left side has type char const *<noident>
drivers/clk/versatile/clk-sp810.c:159:29:    right side has type int
drivers/clk/versatile/clk-sp810.c:159:53: error: incompatible types for operation (<=)
drivers/clk/versatile/clk-sp810.c:159:53:    left side has type char const *<noident>
drivers/clk/versatile/clk-sp810.c:159:53:    right side has type int
drivers/clk/versatile/clk-sp810.c:138:13: warning: symbol 'clk_sp810_of_setup' was not declared. Should it be static?

Acked: Pawel Moll <pawel.moll@arm.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/versatile/clk-sp810.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/versatile/clk-sp810.c b/drivers/clk/versatile/clk-sp810.c
index c6e86a9a2aa3..a96dd8e53fdb 100644
--- a/drivers/clk/versatile/clk-sp810.c
+++ b/drivers/clk/versatile/clk-sp810.c
@@ -135,7 +135,7 @@ static struct clk *clk_sp810_timerclken_of_get(struct of_phandle_args *clkspec,
 	return sp810->timerclken[clkspec->args[0]].clk;
 }
 
-void __init clk_sp810_of_setup(struct device_node *node)
+static void __init clk_sp810_of_setup(struct device_node *node)
 {
 	struct clk_sp810 *sp810 = kzalloc(sizeof(*sp810), GFP_KERNEL);
 	const char *parent_names[2];
@@ -156,7 +156,7 @@ void __init clk_sp810_of_setup(struct device_node *node)
 			"timclk");
 	parent_names[1] = of_clk_get_parent_name(node, sp810->timclk_index);
 
-	if (parent_names[0] <= 0 || parent_names[1] <= 0) {
+	if (!parent_names[0] || !parent_names[1]) {
 		pr_warn("Failed to obtain parent clocks for SP810!\n");
 		return;
 	}

From e45310bfcd21d797f9d36bd4883e600bab645723 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 13:11:31 -0700
Subject: [PATCH 059/135] clk: socfpga: Silence sparse warning

drivers/clk/socfpga/clk-periph.c:79:39: warning: Using plain integer as NULL pointer

Cc: Dinh Nguyen <dinguyen@altera.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/socfpga/clk-periph.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/socfpga/clk-periph.c b/drivers/clk/socfpga/clk-periph.c
index 46531c34ec9b..83aeaa219d14 100644
--- a/drivers/clk/socfpga/clk-periph.c
+++ b/drivers/clk/socfpga/clk-periph.c
@@ -76,7 +76,7 @@ static __init void __socfpga_periph_init(struct device_node *node,
 		periph_clk->shift = div_reg[1];
 		periph_clk->width = div_reg[2];
 	} else {
-		periph_clk->div_reg = 0;
+		periph_clk->div_reg = NULL;
 	}
 
 	rc = of_property_read_u32(node, "fixed-divider", &fixed_div);

From 52127755fe6bc5a7a6d28540938ccdfa2a7b5f90 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 14:03:08 -0700
Subject: [PATCH 060/135] clk: mmp: Silence sparse warnings

drivers/clk/mmp/clk-apbc.c:118:16: warning: symbol 'clk_apbc_ops' was not declared. Should it be static?
drivers/clk/mmp/clk-apmu.c:64:16: warning: symbol 'clk_apmu_ops' was not declared. Should it be static?

Cc: Chao Xie <chao.xie@marvell.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/mmp/clk-apbc.c | 2 +-
 drivers/clk/mmp/clk-apmu.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/mmp/clk-apbc.c b/drivers/clk/mmp/clk-apbc.c
index d14120eaa71f..09d41c717c52 100644
--- a/drivers/clk/mmp/clk-apbc.c
+++ b/drivers/clk/mmp/clk-apbc.c
@@ -115,7 +115,7 @@ static void clk_apbc_unprepare(struct clk_hw *hw)
 		spin_unlock_irqrestore(apbc->lock, flags);
 }
 
-struct clk_ops clk_apbc_ops = {
+static struct clk_ops clk_apbc_ops = {
 	.prepare = clk_apbc_prepare,
 	.unprepare = clk_apbc_unprepare,
 };
diff --git a/drivers/clk/mmp/clk-apmu.c b/drivers/clk/mmp/clk-apmu.c
index abe182b2377f..cdcf2d7f321e 100644
--- a/drivers/clk/mmp/clk-apmu.c
+++ b/drivers/clk/mmp/clk-apmu.c
@@ -61,7 +61,7 @@ static void clk_apmu_disable(struct clk_hw *hw)
 		spin_unlock_irqrestore(apmu->lock, flags);
 }
 
-struct clk_ops clk_apmu_ops = {
+static struct clk_ops clk_apmu_ops = {
 	.enable = clk_apmu_enable,
 	.disable = clk_apmu_disable,
 };

From 6ae5fd381251993a650a7fad51bd9318c19a6c80 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 14:14:57 -0700
Subject: [PATCH 061/135] clk: xgene: Silence sparse warnings
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

drivers/clk/clk-xgene.c:77:43: warning: incorrect type in argument 1 (different address spaces)
drivers/clk/clk-xgene.c:77:43:    expected void *csr
drivers/clk/clk-xgene.c:77:43:    got void [noderef] <asn:2>*
...
drivers/clk/clk-xgene.c: In function ‘xgene_clk_enable’:
drivers/clk/clk-xgene.c:237:3: warning: format ‘%LX’ expects argument of type ‘long long unsigned int’, but argument 4 has type ‘phys_addr_t’ [-Wformat]
drivers/clk/clk-xgene.c:248:3: warning: format ‘%LX’ expects argument of type ‘long long unsigned int’, but argument 4 has type ‘phys_addr_t’ [-Wformat]

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-xgene.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c
index dd8a62d8f11f..f26b3ac36b27 100644
--- a/drivers/clk/clk-xgene.c
+++ b/drivers/clk/clk-xgene.c
@@ -42,12 +42,12 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static inline u32 xgene_clk_read(void *csr)
+static inline u32 xgene_clk_read(void __iomem *csr)
 {
 	return readl_relaxed(csr);
 }
 
-static inline void xgene_clk_write(u32 data, void *csr)
+static inline void xgene_clk_write(u32 data, void __iomem *csr)
 {
 	return writel_relaxed(data, csr);
 }
@@ -119,7 +119,7 @@ static unsigned long xgene_clk_pll_recalc_rate(struct clk_hw *hw,
 	return fvco / nout;
 }
 
-const struct clk_ops xgene_clk_pll_ops = {
+static const struct clk_ops xgene_clk_pll_ops = {
 	.is_enabled = xgene_clk_pll_is_enabled,
 	.recalc_rate = xgene_clk_pll_recalc_rate,
 };
@@ -167,7 +167,7 @@ static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_ty
 {
         const char *clk_name = np->full_name;
         struct clk *clk;
-        void *reg;
+        void __iomem *reg;
 
         reg = of_iomap(np, 0);
         if (reg == NULL) {
@@ -222,20 +222,22 @@ static int xgene_clk_enable(struct clk_hw *hw)
 	struct xgene_clk *pclk = to_xgene_clk(hw);
 	unsigned long flags = 0;
 	u32 data;
+	phys_addr_t reg;
 
 	if (pclk->lock)
 		spin_lock_irqsave(pclk->lock, flags);
 
 	if (pclk->param.csr_reg != NULL) {
 		pr_debug("%s clock enabled\n", pclk->name);
+		reg = __pa(pclk->param.csr_reg);
 		/* First enable the clock */
 		data = xgene_clk_read(pclk->param.csr_reg +
 					pclk->param.reg_clk_offset);
 		data |= pclk->param.reg_clk_mask;
 		xgene_clk_write(data, pclk->param.csr_reg +
 					pclk->param.reg_clk_offset);
-		pr_debug("%s clock PADDR base 0x%016LX clk offset 0x%08X mask 0x%08X value 0x%08X\n",
-			pclk->name, __pa(pclk->param.csr_reg),
+		pr_debug("%s clock PADDR base %pa clk offset 0x%08X mask 0x%08X value 0x%08X\n",
+			pclk->name, &reg,
 			pclk->param.reg_clk_offset, pclk->param.reg_clk_mask,
 			data);
 
@@ -245,8 +247,8 @@ static int xgene_clk_enable(struct clk_hw *hw)
 		data &= ~pclk->param.reg_csr_mask;
 		xgene_clk_write(data, pclk->param.csr_reg +
 					pclk->param.reg_csr_offset);
-		pr_debug("%s CSR RESET PADDR base 0x%016LX csr offset 0x%08X mask 0x%08X value 0x%08X\n",
-			pclk->name, __pa(pclk->param.csr_reg),
+		pr_debug("%s CSR RESET PADDR base %pa csr offset 0x%08X mask 0x%08X value 0x%08X\n",
+			pclk->name, &reg,
 			pclk->param.reg_csr_offset, pclk->param.reg_csr_mask,
 			data);
 	}
@@ -386,7 +388,7 @@ static long xgene_clk_round_rate(struct clk_hw *hw, unsigned long rate,
 	return parent_rate / divider;
 }
 
-const struct clk_ops xgene_clk_ops = {
+static const struct clk_ops xgene_clk_ops = {
 	.enable = xgene_clk_enable,
 	.disable = xgene_clk_disable,
 	.is_enabled = xgene_clk_is_enabled,
@@ -456,7 +458,7 @@ static void __init xgene_devclk_init(struct device_node *np)
 	parameters.csr_reg = NULL;
 	parameters.divider_reg = NULL;
 	for (i = 0; i < 2; i++) {
-		void *map_res;
+		void __iomem *map_res;
 		rc = of_address_to_resource(np, i, &res);
 		if (rc != 0) {
 			if (i == 0) {

From 61ad23a14ac11002addd2b7f9235e15c033f6e3b Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 16:09:33 -0700
Subject: [PATCH 062/135] clk: moxart: Silence sparse warnings

drivers/clk/clk-moxart.c:18:13: warning: symbol 'moxart_of_pll_clk_init' was not declared. Should it be static?
drivers/clk/clk-moxart.c:56:13: warning: symbol 'moxart_of_apb_clk_init' was not declared. Should it be static?

Cc: Jonas Jensen <jonas.jensen@gmail.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-moxart.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk-moxart.c b/drivers/clk/clk-moxart.c
index 30a3b6999e10..5181b89c3cb2 100644
--- a/drivers/clk/clk-moxart.c
+++ b/drivers/clk/clk-moxart.c
@@ -15,7 +15,7 @@
 #include <linux/of_address.h>
 #include <linux/clkdev.h>
 
-void __init moxart_of_pll_clk_init(struct device_node *node)
+static void __init moxart_of_pll_clk_init(struct device_node *node)
 {
 	static void __iomem *base;
 	struct clk *clk, *ref_clk;
@@ -53,7 +53,7 @@ void __init moxart_of_pll_clk_init(struct device_node *node)
 CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock",
 	       moxart_of_pll_clk_init);
 
-void __init moxart_of_apb_clk_init(struct device_node *node)
+static void __init moxart_of_apb_clk_init(struct device_node *node)
 {
 	static void __iomem *base;
 	struct clk *clk, *pll_clk;

From 6c4178163a872cbeef70fd3354222ee4b238e7a2 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Fri, 1 May 2015 16:10:28 -0700
Subject: [PATCH 063/135] clk: u300: Silence sparse warnings

drivers/clk/clk-u300.c:1175:13: warning: symbol 'u300_clk_init' was not declared. Should it be static?

Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-u300.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c
index 406bfc1375b2..18bf5e576b93 100644
--- a/drivers/clk/clk-u300.c
+++ b/drivers/clk/clk-u300.c
@@ -12,6 +12,7 @@
 #include <linux/clk-provider.h>
 #include <linux/spinlock.h>
 #include <linux/of.h>
+#include <linux/platform_data/clk-u300.h>
 
 /* APP side SYSCON registers */
 /* CLK Control Register 16bit (R/W) */

From 64a12c56addcb2d15ff752874abbe553a5f2a45b Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Thu, 14 May 2015 17:38:21 -0700
Subject: [PATCH 064/135] clk: Kconfig: Move bcm Kconfig into clk menu

Having this Kconfig sourced outside the clk menu means the option
is under the "Device Drivers" menu instead of the "Common Clock
Framework" menu. Move it so that the bcm clock config options are
in the right place.

Cc: Alex Elder <elder@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 9897f353bf1a..67e3a84d2805 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -150,11 +150,11 @@ config COMMON_CLK_CDCE706
 	---help---
 	  This driver supports TI CDCE706 programmable 3-PLL clock synthesizer.
 
+source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/qcom/Kconfig"
 
 endmenu
 
-source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/mvebu/Kconfig"
 
 source "drivers/clk/samsung/Kconfig"

From 2885c3b2a3da7902314fa1d0a5b603eeea7c7302 Mon Sep 17 00:00:00 2001
From: Chanwoo Choi <cw00.choi@samsung.com>
Date: Mon, 27 Apr 2015 18:29:52 +0900
Subject: [PATCH 065/135] clk: Show correct information when fail to set clock
 rate

This patch shows the correct information for debugging when fail
to set clock rate because original error message shows the error
value instead of current clock rate.

Cc: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-conf.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
index 48a65b2b4027..35a396bc9672 100644
--- a/drivers/clk/clk-conf.c
+++ b/drivers/clk/clk-conf.c
@@ -106,8 +106,9 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
 
 			rc = clk_set_rate(clk, rate);
 			if (rc < 0)
-				pr_err("clk: couldn't set %s clock rate: %d\n",
-				       __clk_get_name(clk), rc);
+				pr_err("clk: couldn't set %s clk rate to %d (%d), current rate: %ld\n",
+				       __clk_get_name(clk), rate, rc,
+				       clk_get_rate(clk));
 			clk_put(clk);
 		}
 		index++;

From 8a3d9c164152e461e5f80db65aaaa0fbfdb2eed3 Mon Sep 17 00:00:00 2001
From: Rob Herring <robh@kernel.org>
Date: Mon, 11 May 2015 17:25:19 -0500
Subject: [PATCH 066/135] dt-bindings: Add pxa1928 clock binding

This adds the clock binding documentation for the Marvell PXA1928 SOC.
The PXA1928 has 3 clock control blocks for different subsystems of the
chip.

Signed-off-by: Rob Herring <robh@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 .../bindings/clock/marvell,pxa1928.txt        | 21 +++++++
 include/dt-bindings/clock/marvell,pxa1928.h   | 57 +++++++++++++++++++
 2 files changed, 78 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/marvell,pxa1928.txt
 create mode 100644 include/dt-bindings/clock/marvell,pxa1928.h

diff --git a/Documentation/devicetree/bindings/clock/marvell,pxa1928.txt b/Documentation/devicetree/bindings/clock/marvell,pxa1928.txt
new file mode 100644
index 000000000000..809c5a2d8d9d
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/marvell,pxa1928.txt
@@ -0,0 +1,21 @@
+* Marvell PXA1928 Clock Controllers
+
+The PXA1928 clock subsystem generates and supplies clock to various
+controllers within the PXA1928 SoC. The PXA1928 contains 3 clock controller
+blocks called APMU, MPMU, and APBC roughly corresponding to internal buses.
+
+Required Properties:
+
+- compatible: should be one of the following.
+  - "marvell,pxa1928-apmu" - APMU controller compatible
+  - "marvell,pxa1928-mpmu" - MPMU controller compatible
+  - "marvell,pxa1928-apbc" - APBC controller compatible
+- reg: physical base address of the clock controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use the clock controller
+phandle and this identifier to specify the clock which they consume.
+
+All these identifiers can be found in <dt-bindings/clock/marvell,pxa1928.h>.
diff --git a/include/dt-bindings/clock/marvell,pxa1928.h b/include/dt-bindings/clock/marvell,pxa1928.h
new file mode 100644
index 000000000000..d4f2e18919ff
--- /dev/null
+++ b/include/dt-bindings/clock/marvell,pxa1928.h
@@ -0,0 +1,57 @@
+#ifndef __DTS_MARVELL_PXA1928_CLOCK_H
+#define __DTS_MARVELL_PXA1928_CLOCK_H
+
+/*
+ * Clock ID values here correspond to the control register offset/4.
+ */
+
+/* apb peripherals */
+#define PXA1928_CLK_RTC			0x00
+#define PXA1928_CLK_TWSI0		0x01
+#define PXA1928_CLK_TWSI1		0x02
+#define PXA1928_CLK_TWSI2		0x03
+#define PXA1928_CLK_TWSI3		0x04
+#define PXA1928_CLK_OWIRE		0x05
+#define PXA1928_CLK_KPC			0x06
+#define PXA1928_CLK_TB_ROTARY		0x07
+#define PXA1928_CLK_SW_JTAG		0x08
+#define PXA1928_CLK_TIMER1		0x09
+#define PXA1928_CLK_UART0		0x0b
+#define PXA1928_CLK_UART1		0x0c
+#define PXA1928_CLK_UART2		0x0d
+#define PXA1928_CLK_GPIO		0x0e
+#define PXA1928_CLK_PWM0		0x0f
+#define PXA1928_CLK_PWM1		0x10
+#define PXA1928_CLK_PWM2		0x11
+#define PXA1928_CLK_PWM3		0x12
+#define PXA1928_CLK_SSP0		0x13
+#define PXA1928_CLK_SSP1		0x14
+#define PXA1928_CLK_SSP2		0x15
+
+#define PXA1928_CLK_TWSI4		0x1f
+#define PXA1928_CLK_TWSI5		0x20
+#define PXA1928_CLK_UART3		0x22
+#define PXA1928_CLK_THSENS_GLOB		0x24
+#define PXA1928_CLK_THSENS_CPU		0x26
+#define PXA1928_CLK_THSENS_VPU		0x27
+#define PXA1928_CLK_THSENS_GC		0x28
+#define PXA1928_APBC_NR_CLKS		0x30
+
+
+/* axi peripherals */
+#define PXA1928_CLK_SDH0		0x15
+#define PXA1928_CLK_SDH1		0x16
+#define PXA1928_CLK_USB			0x17
+#define PXA1928_CLK_NAND		0x18
+#define PXA1928_CLK_DMA			0x19
+
+#define PXA1928_CLK_SDH2		0x3a
+#define PXA1928_CLK_SDH3		0x3b
+#define PXA1928_CLK_HSIC		0x3e
+#define PXA1928_CLK_SDH4		0x57
+#define PXA1928_CLK_GC3D		0x5d
+#define PXA1928_CLK_GC2D		0x5f
+
+#define PXA1928_APMU_NR_CLKS		0x60
+
+#endif

From df5338d9fe5d607cdbc68d8432cbfdc9a942a679 Mon Sep 17 00:00:00 2001
From: Rob Herring <robh@kernel.org>
Date: Mon, 11 May 2015 17:25:20 -0500
Subject: [PATCH 067/135] clk: mmp: add PXA1928 clock support

Add initial clock support for Marvell PXA1928. The PXA1928 is a mobile
SOC and is similar to other MMP/PXA series of SOCs, so a lot of the
existing infrastructure is reused here.

Currently the PLLs are just fixed clocks, and not all leaf clocks are
implemented.

Signed-off-by: Rob Herring <robh@kernel.org>
Cc: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/mmp/Makefile         |   2 +
 drivers/clk/mmp/clk-of-pxa1928.c | 265 +++++++++++++++++++++++++++++++
 2 files changed, 267 insertions(+)
 create mode 100644 drivers/clk/mmp/clk-of-pxa1928.c

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 3caaf7cc169c..9d4bc41e4239 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -12,3 +12,5 @@ obj-$(CONFIG_MACH_MMP2_DT) += clk-of-mmp2.o
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
 obj-$(CONFIG_CPU_MMP2) += clk-mmp2.o
+
+obj-y += clk-of-pxa1928.o
diff --git a/drivers/clk/mmp/clk-of-pxa1928.c b/drivers/clk/mmp/clk-of-pxa1928.c
new file mode 100644
index 000000000000..433a5ae1eae0
--- /dev/null
+++ b/drivers/clk/mmp/clk-of-pxa1928.c
@@ -0,0 +1,265 @@
+/*
+ * pxa1928 clock framework source file
+ *
+ * Copyright (C) 2015 Linaro, Ltd.
+ * Rob Herring <robh@kernel.org>
+ *
+ * Based on drivers/clk/mmp/clk-of-mmp2.c:
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/clock/marvell,pxa1928.h>
+
+#include "clk.h"
+#include "reset.h"
+
+#define MPMU_UART_PLL	0x14
+
+struct pxa1928_clk_unit {
+	struct mmp_clk_unit unit;
+	void __iomem *mpmu_base;
+	void __iomem *apmu_base;
+	void __iomem *apbc_base;
+	void __iomem *apbcp_base;
+};
+
+static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
+	{0, "clk32", NULL, CLK_IS_ROOT, 32768},
+	{0, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
+	{0, "pll1_624", NULL, CLK_IS_ROOT, 624000000},
+	{0, "pll5p", NULL, CLK_IS_ROOT, 832000000},
+	{0, "pll5", NULL, CLK_IS_ROOT, 1248000000},
+	{0, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
+};
+
+static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
+	{0, "pll1_d2", "pll1_624", 1, 2, 0},
+	{0, "pll1_d9", "pll1_624", 1, 9, 0},
+	{0, "pll1_d12", "pll1_624", 1, 12, 0},
+	{0, "pll1_d16", "pll1_624", 1, 16, 0},
+	{0, "pll1_d20", "pll1_624", 1, 20, 0},
+	{0, "pll1_416", "pll1_624", 2, 3, 0},
+	{0, "vctcxo_d2", "vctcxo", 1, 2, 0},
+	{0, "vctcxo_d4", "vctcxo", 1, 4, 0},
+};
+
+static struct mmp_clk_factor_masks uart_factor_masks = {
+	.factor = 2,
+	.num_mask = 0x1fff,
+	.den_mask = 0x1fff,
+	.num_shift = 16,
+	.den_shift = 0,
+};
+
+static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
+	{.num = 832, .den = 234},	/*58.5MHZ */
+	{.num = 1, .den = 1},		/*26MHZ */
+};
+
+static void pxa1928_pll_init(struct pxa1928_clk_unit *pxa_unit)
+{
+	struct clk *clk;
+	struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+	mmp_register_fixed_rate_clks(unit, fixed_rate_clks,
+					ARRAY_SIZE(fixed_rate_clks));
+
+	mmp_register_fixed_factor_clks(unit, fixed_factor_clks,
+					ARRAY_SIZE(fixed_factor_clks));
+
+	clk = mmp_clk_register_factor("uart_pll", "pll1_416",
+				CLK_SET_RATE_PARENT,
+				pxa_unit->mpmu_base + MPMU_UART_PLL,
+				&uart_factor_masks, uart_factor_tbl,
+				ARRAY_SIZE(uart_factor_tbl), NULL);
+}
+
+static DEFINE_SPINLOCK(uart0_lock);
+static DEFINE_SPINLOCK(uart1_lock);
+static DEFINE_SPINLOCK(uart2_lock);
+static DEFINE_SPINLOCK(uart3_lock);
+static const char *uart_parent_names[] = {"uart_pll", "vctcxo"};
+
+static DEFINE_SPINLOCK(ssp0_lock);
+static DEFINE_SPINLOCK(ssp1_lock);
+static const char *ssp_parent_names[] = {"vctcxo_d4", "vctcxo_d2", "vctcxo", "pll1_d12"};
+
+static DEFINE_SPINLOCK(reset_lock);
+
+static struct mmp_param_mux_clk apbc_mux_clks[] = {
+	{0, "uart0_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART0 * 4, 4, 3, 0, &uart0_lock},
+	{0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART1 * 4, 4, 3, 0, &uart1_lock},
+	{0, "uart2_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART2 * 4, 4, 3, 0, &uart2_lock},
+	{0, "uart3_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_UART3 * 4, 4, 3, 0, &uart3_lock},
+	{0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_SSP0 * 4, 4, 3, 0, &ssp0_lock},
+	{0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_SSP1 * 4, 4, 3, 0, &ssp1_lock},
+};
+
+static struct mmp_param_gate_clk apbc_gate_clks[] = {
+	{PXA1928_CLK_TWSI0, "twsi0_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI0 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_TWSI1, "twsi1_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI1 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_TWSI2, "twsi2_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI2 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_TWSI3, "twsi3_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI3 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_TWSI4, "twsi4_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI4 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_TWSI5, "twsi5_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_TWSI5 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_GPIO, "gpio_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_GPIO * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_KPC, "kpc_clk", "clk32", CLK_SET_RATE_PARENT, PXA1928_CLK_KPC * 4, 0x3, 0x3, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL},
+	{PXA1928_CLK_RTC, "rtc_clk", "clk32", CLK_SET_RATE_PARENT, PXA1928_CLK_RTC * 4, 0x83, 0x83, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL},
+	{PXA1928_CLK_PWM0, "pwm0_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM0 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_PWM1, "pwm1_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM1 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_PWM2, "pwm2_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM2 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	{PXA1928_CLK_PWM3, "pwm3_clk", "vctcxo", CLK_SET_RATE_PARENT, PXA1928_CLK_PWM3 * 4, 0x3, 0x3, 0x0, 0, &reset_lock},
+	/* The gate clocks has mux parent. */
+	{PXA1928_CLK_UART0, "uart0_clk", "uart0_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART0 * 4, 0x3, 0x3, 0x0, 0, &uart0_lock},
+	{PXA1928_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART1 * 4, 0x3, 0x3, 0x0, 0, &uart1_lock},
+	{PXA1928_CLK_UART2, "uart2_clk", "uart2_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART2 * 4, 0x3, 0x3, 0x0, 0, &uart2_lock},
+	{PXA1928_CLK_UART3, "uart3_clk", "uart3_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_UART3 * 4, 0x3, 0x3, 0x0, 0, &uart3_lock},
+	{PXA1928_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_SSP0 * 4, 0x3, 0x3, 0x0, 0, &ssp0_lock},
+	{PXA1928_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, PXA1928_CLK_SSP1 * 4, 0x3, 0x3, 0x0, 0, &ssp1_lock},
+};
+
+static void pxa1928_apb_periph_clk_init(struct pxa1928_clk_unit *pxa_unit)
+{
+	struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+	mmp_register_mux_clks(unit, apbc_mux_clks, pxa_unit->apbc_base,
+				ARRAY_SIZE(apbc_mux_clks));
+
+	mmp_register_gate_clks(unit, apbc_gate_clks, pxa_unit->apbc_base,
+				ARRAY_SIZE(apbc_gate_clks));
+}
+
+static DEFINE_SPINLOCK(sdh0_lock);
+static DEFINE_SPINLOCK(sdh1_lock);
+static DEFINE_SPINLOCK(sdh2_lock);
+static DEFINE_SPINLOCK(sdh3_lock);
+static DEFINE_SPINLOCK(sdh4_lock);
+static const char *sdh_parent_names[] = {"pll1_624", "pll5p", "pll5", "pll1_416"};
+
+static DEFINE_SPINLOCK(usb_lock);
+
+static struct mmp_param_mux_clk apmu_mux_clks[] = {
+	{0, "sdh_mux", sdh_parent_names, ARRAY_SIZE(sdh_parent_names), CLK_SET_RATE_PARENT, PXA1928_CLK_SDH0 * 4, 8, 2, 0, &sdh0_lock},
+};
+
+static struct mmp_param_div_clk apmu_div_clks[] = {
+	{0, "sdh_div", "sdh_mux", 0, PXA1928_CLK_SDH0 * 4, 10, 4, CLK_DIVIDER_ONE_BASED, &sdh0_lock},
+};
+
+static struct mmp_param_gate_clk apmu_gate_clks[] = {
+	{PXA1928_CLK_USB, "usb_clk", "usb_pll", 0, PXA1928_CLK_USB * 4, 0x9, 0x9, 0x0, 0, &usb_lock},
+	{PXA1928_CLK_HSIC, "hsic_clk", "usb_pll", 0, PXA1928_CLK_HSIC * 4, 0x9, 0x9, 0x0, 0, &usb_lock},
+	/* The gate clocks has mux parent. */
+	{PXA1928_CLK_SDH0, "sdh0_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH0 * 4, 0x1b, 0x1b, 0x0, 0, &sdh0_lock},
+	{PXA1928_CLK_SDH1, "sdh1_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH1 * 4, 0x1b, 0x1b, 0x0, 0, &sdh1_lock},
+	{PXA1928_CLK_SDH2, "sdh2_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH2 * 4, 0x1b, 0x1b, 0x0, 0, &sdh2_lock},
+	{PXA1928_CLK_SDH3, "sdh3_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH3 * 4, 0x1b, 0x1b, 0x0, 0, &sdh3_lock},
+	{PXA1928_CLK_SDH4, "sdh4_clk", "sdh_div", CLK_SET_RATE_PARENT, PXA1928_CLK_SDH4 * 4, 0x1b, 0x1b, 0x0, 0, &sdh4_lock},
+};
+
+static void pxa1928_axi_periph_clk_init(struct pxa1928_clk_unit *pxa_unit)
+{
+	struct mmp_clk_unit *unit = &pxa_unit->unit;
+
+	mmp_register_mux_clks(unit, apmu_mux_clks, pxa_unit->apmu_base,
+				ARRAY_SIZE(apmu_mux_clks));
+
+	mmp_register_div_clks(unit, apmu_div_clks, pxa_unit->apmu_base,
+				ARRAY_SIZE(apmu_div_clks));
+
+	mmp_register_gate_clks(unit, apmu_gate_clks, pxa_unit->apmu_base,
+				ARRAY_SIZE(apmu_gate_clks));
+}
+
+static void pxa1928_clk_reset_init(struct device_node *np,
+				struct pxa1928_clk_unit *pxa_unit)
+{
+	struct mmp_clk_reset_cell *cells;
+	int i, base, nr_resets;
+
+	nr_resets = ARRAY_SIZE(apbc_gate_clks);
+	cells = kcalloc(nr_resets, sizeof(*cells), GFP_KERNEL);
+	if (!cells)
+		return;
+
+	base = 0;
+	for (i = 0; i < nr_resets; i++) {
+		cells[base + i].clk_id = apbc_gate_clks[i].id;
+		cells[base + i].reg =
+			pxa_unit->apbc_base + apbc_gate_clks[i].offset;
+		cells[base + i].flags = 0;
+		cells[base + i].lock = apbc_gate_clks[i].lock;
+		cells[base + i].bits = 0x4;
+	}
+
+	mmp_clk_reset_register(np, cells, nr_resets);
+}
+
+static void __init pxa1928_mpmu_clk_init(struct device_node *np)
+{
+	struct pxa1928_clk_unit *pxa_unit;
+
+	pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
+	if (!pxa_unit)
+		return;
+
+	pxa_unit->mpmu_base = of_iomap(np, 0);
+	if (!pxa_unit->mpmu_base) {
+		pr_err("failed to map mpmu registers\n");
+		return;
+	}
+
+	pxa1928_pll_init(pxa_unit);
+}
+CLK_OF_DECLARE(pxa1928_mpmu_clk, "marvell,pxa1928-mpmu", pxa1928_mpmu_clk_init);
+
+static void __init pxa1928_apmu_clk_init(struct device_node *np)
+{
+	struct pxa1928_clk_unit *pxa_unit;
+
+	pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
+	if (!pxa_unit)
+		return;
+
+	pxa_unit->apmu_base = of_iomap(np, 0);
+	if (!pxa_unit->apmu_base) {
+		pr_err("failed to map apmu registers\n");
+		return;
+	}
+
+	mmp_clk_init(np, &pxa_unit->unit, PXA1928_APMU_NR_CLKS);
+
+	pxa1928_axi_periph_clk_init(pxa_unit);
+}
+CLK_OF_DECLARE(pxa1928_apmu_clk, "marvell,pxa1928-apmu", pxa1928_apmu_clk_init);
+
+static void __init pxa1928_apbc_clk_init(struct device_node *np)
+{
+	struct pxa1928_clk_unit *pxa_unit;
+
+	pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
+	if (!pxa_unit)
+		return;
+
+	pxa_unit->apbc_base = of_iomap(np, 0);
+	if (!pxa_unit->apbc_base) {
+		pr_err("failed to map apbc registers\n");
+		return;
+	}
+
+	mmp_clk_init(np, &pxa_unit->unit, PXA1928_APBC_NR_CLKS);
+
+	pxa1928_apb_periph_clk_init(pxa_unit);
+	pxa1928_clk_reset_init(np, pxa_unit);
+}
+CLK_OF_DECLARE(pxa1928_apbc_clk, "marvell,pxa1928-apbc", pxa1928_apbc_clk_init);

From 95f589814c8af85fa673320bf319ffe8d721dd74 Mon Sep 17 00:00:00 2001
From: Ricky Liang <jcliang@chromium.org>
Date: Mon, 18 May 2015 22:00:26 +0800
Subject: [PATCH 068/135] clk: mediatek: Initialize clk_init_data

The variable init (struct clk_init_data) is allocated on the stack.
We weren't initializing the .flags field, so it contains random junk,
which can cause all kinds of interesting issues when the flags are
parsed by clk_register.

Signed-off-by: Ricky Liang <jcliang@chromium.org>
Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/mediatek/clk-gate.c | 2 +-
 drivers/clk/mediatek/clk-pll.c  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
index 9d77ee3256f2..57020368a693 100644
--- a/drivers/clk/mediatek/clk-gate.c
+++ b/drivers/clk/mediatek/clk-gate.c
@@ -109,7 +109,7 @@ struct clk *mtk_clk_register_gate(
 {
 	struct mtk_clk_gate *cg;
 	struct clk *clk;
-	struct clk_init_data init;
+	struct clk_init_data init = {};
 
 	cg = kzalloc(sizeof(*cg), GFP_KERNEL);
 	if (!cg)
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index 66154caf992a..44409e98c52f 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -268,7 +268,7 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
 		void __iomem *base)
 {
 	struct mtk_clk_pll *pll;
-	struct clk_init_data init;
+	struct clk_init_data init = {};
 	struct clk *clk;
 	const char *parent_name = "clk26m";
 

From 301c5d29402e590ea893fe7ddc83a00a71994cba Mon Sep 17 00:00:00 2001
From: Zhiwu Song <Zhiwu.Song@csr.com>
Date: Wed, 20 May 2015 08:50:33 +0000
Subject: [PATCH 069/135] clk: sirf: add CSR atlas7 clk and reset support

the hardware node includes both clock and reset support, so it
is named as "car".
this patch implements Flexible clocks(mux, divider, gate), Selectable
clock(mux, divider, gate), root clock(gate),leaf clock(gate), others.
it also implements the reset controller functionality.

Signed-off-by: Zhiwu Song <Zhiwu.Song@csr.com>
Signed-off-by: Guo Zeng <Guo.Zeng@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 .../bindings/clock/csr,atlas7-car.txt         |   55 +
 drivers/clk/sirf/Makefile                     |    2 +-
 drivers/clk/sirf/clk-atlas7.c                 | 1632 +++++++++++++++++
 3 files changed, 1688 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/csr,atlas7-car.txt
 create mode 100644 drivers/clk/sirf/clk-atlas7.c

diff --git a/Documentation/devicetree/bindings/clock/csr,atlas7-car.txt b/Documentation/devicetree/bindings/clock/csr,atlas7-car.txt
new file mode 100644
index 000000000000..54d6d1358339
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/csr,atlas7-car.txt
@@ -0,0 +1,55 @@
+* Clock and reset bindings for CSR atlas7
+
+Required properties:
+- compatible: Should be "sirf,atlas7-car"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- #reset-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.
+The ID list atlas7_clks defined in drivers/clk/sirf/clk-atlas7.c
+
+The reset consumer should specify the desired reset by having the reset
+ID in its "reset" phandle cell.
+The ID list atlas7_reset_unit defined in drivers/clk/sirf/clk-atlas7.c
+
+Examples: Clock and reset controller node:
+
+car: clock-controller@18620000 {
+	compatible = "sirf,atlas7-car";
+	reg = <0x18620000 0x1000>;
+	#clock-cells = <1>;
+	#reset-cells = <1>;
+};
+
+Examples: Consumers using clock or reset:
+
+timer@10dc0000 {
+	compatible = "sirf,macro-tick";
+	reg = <0x10dc0000 0x1000>;
+	clocks = <&car 54>;
+	interrupts = <0 0 0>,
+		   <0 1 0>,
+		   <0 2 0>,
+		   <0 49 0>,
+		   <0 50 0>,
+		   <0 51 0>;
+};
+
+uart1: uart@18020000 {
+	cell-index = <1>;
+	compatible = "sirf,macro-uart";
+	reg = <0x18020000 0x1000>;
+	clocks = <&clks 95>;
+	interrupts = <0 18 0>;
+	fifosize = <32>;
+};
+
+vpp@13110000 {
+	compatible = "sirf,prima2-vpp";
+	reg = <0x13110000 0x10000>;
+	interrupts = <0 31 0>;
+	clocks = <&car 85>;
+	resets = <&car 29>;
+};
diff --git a/drivers/clk/sirf/Makefile b/drivers/clk/sirf/Makefile
index 36b8e203f6e7..09b4210d9124 100644
--- a/drivers/clk/sirf/Makefile
+++ b/drivers/clk/sirf/Makefile
@@ -2,4 +2,4 @@
 # Makefile for sirf specific clk
 #
 
-obj-$(CONFIG_ARCH_SIRF) += clk-prima2.o clk-atlas6.o
+obj-$(CONFIG_ARCH_SIRF) += clk-prima2.o clk-atlas6.o clk-atlas7.o
diff --git a/drivers/clk/sirf/clk-atlas7.c b/drivers/clk/sirf/clk-atlas7.c
new file mode 100644
index 000000000000..db8ab691dbf6
--- /dev/null
+++ b/drivers/clk/sirf/clk-atlas7.c
@@ -0,0 +1,1632 @@
+/*
+ * Clock tree for CSR SiRFAtlas7
+ *
+ * Copyright (c) 2014 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/of_address.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+
+#define SIRFSOC_CLKC_MEMPLL_AB_FREQ          0x0000
+#define SIRFSOC_CLKC_MEMPLL_AB_SSC           0x0004
+#define SIRFSOC_CLKC_MEMPLL_AB_CTRL0         0x0008
+#define SIRFSOC_CLKC_MEMPLL_AB_CTRL1         0x000c
+#define SIRFSOC_CLKC_MEMPLL_AB_STATUS        0x0010
+#define SIRFSOC_CLKC_MEMPLL_AB_SSRAM_ADDR    0x0014
+#define SIRFSOC_CLKC_MEMPLL_AB_SSRAM_DATA    0x0018
+
+#define SIRFSOC_CLKC_CPUPLL_AB_FREQ          0x001c
+#define SIRFSOC_CLKC_CPUPLL_AB_SSC           0x0020
+#define SIRFSOC_CLKC_CPUPLL_AB_CTRL0         0x0024
+#define SIRFSOC_CLKC_CPUPLL_AB_CTRL1         0x0028
+#define SIRFSOC_CLKC_CPUPLL_AB_STATUS        0x002c
+
+#define SIRFSOC_CLKC_SYS0PLL_AB_FREQ         0x0030
+#define SIRFSOC_CLKC_SYS0PLL_AB_SSC          0x0034
+#define SIRFSOC_CLKC_SYS0PLL_AB_CTRL0        0x0038
+#define SIRFSOC_CLKC_SYS0PLL_AB_CTRL1        0x003c
+#define SIRFSOC_CLKC_SYS0PLL_AB_STATUS       0x0040
+
+#define SIRFSOC_CLKC_SYS1PLL_AB_FREQ         0x0044
+#define SIRFSOC_CLKC_SYS1PLL_AB_SSC          0x0048
+#define SIRFSOC_CLKC_SYS1PLL_AB_CTRL0        0x004c
+#define SIRFSOC_CLKC_SYS1PLL_AB_CTRL1        0x0050
+#define SIRFSOC_CLKC_SYS1PLL_AB_STATUS       0x0054
+
+#define SIRFSOC_CLKC_SYS2PLL_AB_FREQ         0x0058
+#define SIRFSOC_CLKC_SYS2PLL_AB_SSC          0x005c
+#define SIRFSOC_CLKC_SYS2PLL_AB_CTRL0        0x0060
+#define SIRFSOC_CLKC_SYS2PLL_AB_CTRL1        0x0064
+#define SIRFSOC_CLKC_SYS2PLL_AB_STATUS       0x0068
+
+#define SIRFSOC_CLKC_SYS3PLL_AB_FREQ         0x006c
+#define SIRFSOC_CLKC_SYS3PLL_AB_SSC          0x0070
+#define SIRFSOC_CLKC_SYS3PLL_AB_CTRL0        0x0074
+#define SIRFSOC_CLKC_SYS3PLL_AB_CTRL1        0x0078
+#define SIRFSOC_CLKC_SYS3PLL_AB_STATUS       0x007c
+
+#define SIRFSOC_ABPLL_CTRL0_SSEN     0x00001000
+#define SIRFSOC_ABPLL_CTRL0_BYPASS   0x00000010
+#define SIRFSOC_ABPLL_CTRL0_RESET    0x00000001
+
+#define SIRFSOC_CLKC_AUDIO_DTO_INC           0x0088
+#define SIRFSOC_CLKC_DISP0_DTO_INC           0x008c
+#define SIRFSOC_CLKC_DISP1_DTO_INC           0x0090
+
+#define SIRFSOC_CLKC_AUDIO_DTO_SRC           0x0094
+#define SIRFSOC_CLKC_AUDIO_DTO_ENA           0x0098
+#define SIRFSOC_CLKC_AUDIO_DTO_DROFF         0x009c
+
+#define SIRFSOC_CLKC_DISP0_DTO_SRC           0x00a0
+#define SIRFSOC_CLKC_DISP0_DTO_ENA           0x00a4
+#define SIRFSOC_CLKC_DISP0_DTO_DROFF         0x00a8
+
+#define SIRFSOC_CLKC_DISP1_DTO_SRC           0x00ac
+#define SIRFSOC_CLKC_DISP1_DTO_ENA           0x00b0
+#define SIRFSOC_CLKC_DISP1_DTO_DROFF         0x00b4
+
+#define SIRFSOC_CLKC_I2S_CLK_SEL             0x00b8
+#define SIRFSOC_CLKC_I2S_SEL_STAT            0x00bc
+
+#define SIRFSOC_CLKC_USBPHY_CLKDIV_CFG       0x00c0
+#define SIRFSOC_CLKC_USBPHY_CLKDIV_ENA       0x00c4
+#define SIRFSOC_CLKC_USBPHY_CLK_SEL          0x00c8
+#define SIRFSOC_CLKC_USBPHY_CLK_SEL_STAT     0x00cc
+
+#define SIRFSOC_CLKC_BTSS_CLKDIV_CFG         0x00d0
+#define SIRFSOC_CLKC_BTSS_CLKDIV_ENA         0x00d4
+#define SIRFSOC_CLKC_BTSS_CLK_SEL            0x00d8
+#define SIRFSOC_CLKC_BTSS_CLK_SEL_STAT       0x00dc
+
+#define SIRFSOC_CLKC_RGMII_CLKDIV_CFG        0x00e0
+#define SIRFSOC_CLKC_RGMII_CLKDIV_ENA        0x00e4
+#define SIRFSOC_CLKC_RGMII_CLK_SEL           0x00e8
+#define SIRFSOC_CLKC_RGMII_CLK_SEL_STAT      0x00ec
+
+#define SIRFSOC_CLKC_CPU_CLKDIV_CFG          0x00f0
+#define SIRFSOC_CLKC_CPU_CLKDIV_ENA          0x00f4
+#define SIRFSOC_CLKC_CPU_CLK_SEL             0x00f8
+#define SIRFSOC_CLKC_CPU_CLK_SEL_STAT        0x00fc
+
+#define SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG      0x0100
+#define SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA      0x0104
+#define SIRFSOC_CLKC_SDPHY01_CLK_SEL         0x0108
+#define SIRFSOC_CLKC_SDPHY01_CLK_SEL_STAT    0x010c
+
+#define SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG      0x0110
+#define SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA      0x0114
+#define SIRFSOC_CLKC_SDPHY23_CLK_SEL         0x0118
+#define SIRFSOC_CLKC_SDPHY23_CLK_SEL_STAT    0x011c
+
+#define SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG      0x0120
+#define SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA      0x0124
+#define SIRFSOC_CLKC_SDPHY45_CLK_SEL         0x0128
+#define SIRFSOC_CLKC_SDPHY45_CLK_SEL_STAT    0x012c
+
+#define SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG      0x0130
+#define SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA      0x0134
+#define SIRFSOC_CLKC_SDPHY67_CLK_SEL         0x0138
+#define SIRFSOC_CLKC_SDPHY67_CLK_SEL_STAT    0x013c
+
+#define SIRFSOC_CLKC_CAN_CLKDIV_CFG          0x0140
+#define SIRFSOC_CLKC_CAN_CLKDIV_ENA          0x0144
+#define SIRFSOC_CLKC_CAN_CLK_SEL             0x0148
+#define SIRFSOC_CLKC_CAN_CLK_SEL_STAT        0x014c
+
+#define SIRFSOC_CLKC_DEINT_CLKDIV_CFG        0x0150
+#define SIRFSOC_CLKC_DEINT_CLKDIV_ENA        0x0154
+#define SIRFSOC_CLKC_DEINT_CLK_SEL           0x0158
+#define SIRFSOC_CLKC_DEINT_CLK_SEL_STAT      0x015c
+
+#define SIRFSOC_CLKC_NAND_CLKDIV_CFG         0x0160
+#define SIRFSOC_CLKC_NAND_CLKDIV_ENA         0x0164
+#define SIRFSOC_CLKC_NAND_CLK_SEL            0x0168
+#define SIRFSOC_CLKC_NAND_CLK_SEL_STAT       0x016c
+
+#define SIRFSOC_CLKC_DISP0_CLKDIV_CFG        0x0170
+#define SIRFSOC_CLKC_DISP0_CLKDIV_ENA        0x0174
+#define SIRFSOC_CLKC_DISP0_CLK_SEL           0x0178
+#define SIRFSOC_CLKC_DISP0_CLK_SEL_STAT      0x017c
+
+#define SIRFSOC_CLKC_DISP1_CLKDIV_CFG        0x0180
+#define SIRFSOC_CLKC_DISP1_CLKDIV_ENA        0x0184
+#define SIRFSOC_CLKC_DISP1_CLK_SEL           0x0188
+#define SIRFSOC_CLKC_DISP1_CLK_SEL_STAT      0x018c
+
+#define SIRFSOC_CLKC_GPU_CLKDIV_CFG          0x0190
+#define SIRFSOC_CLKC_GPU_CLKDIV_ENA          0x0194
+#define SIRFSOC_CLKC_GPU_CLK_SEL             0x0198
+#define SIRFSOC_CLKC_GPU_CLK_SEL_STAT        0x019c
+
+#define SIRFSOC_CLKC_GNSS_CLKDIV_CFG         0x01a0
+#define SIRFSOC_CLKC_GNSS_CLKDIV_ENA         0x01a4
+#define SIRFSOC_CLKC_GNSS_CLK_SEL            0x01a8
+#define SIRFSOC_CLKC_GNSS_CLK_SEL_STAT       0x01ac
+
+#define SIRFSOC_CLKC_SHARED_DIVIDER_CFG0     0x01b0
+#define SIRFSOC_CLKC_SHARED_DIVIDER_CFG1     0x01b4
+#define SIRFSOC_CLKC_SHARED_DIVIDER_ENA      0x01b8
+
+#define SIRFSOC_CLKC_SYS_CLK_SEL             0x01bc
+#define SIRFSOC_CLKC_SYS_CLK_SEL_STAT        0x01c0
+#define SIRFSOC_CLKC_IO_CLK_SEL              0x01c4
+#define SIRFSOC_CLKC_IO_CLK_SEL_STAT         0x01c8
+#define SIRFSOC_CLKC_G2D_CLK_SEL             0x01cc
+#define SIRFSOC_CLKC_G2D_CLK_SEL_STAT        0x01d0
+#define SIRFSOC_CLKC_JPENC_CLK_SEL           0x01d4
+#define SIRFSOC_CLKC_JPENC_CLK_SEL_STAT      0x01d8
+#define SIRFSOC_CLKC_VDEC_CLK_SEL            0x01dc
+#define SIRFSOC_CLKC_VDEC_CLK_SEL_STAT       0x01e0
+#define SIRFSOC_CLKC_GMAC_CLK_SEL            0x01e4
+#define SIRFSOC_CLKC_GMAC_CLK_SEL_STAT       0x01e8
+#define SIRFSOC_CLKC_USB_CLK_SEL             0x01ec
+#define SIRFSOC_CLKC_USB_CLK_SEL_STAT        0x01f0
+#define SIRFSOC_CLKC_KAS_CLK_SEL             0x01f4
+#define SIRFSOC_CLKC_KAS_CLK_SEL_STAT        0x01f8
+#define SIRFSOC_CLKC_SEC_CLK_SEL             0x01fc
+#define SIRFSOC_CLKC_SEC_CLK_SEL_STAT        0x0200
+#define SIRFSOC_CLKC_SDR_CLK_SEL             0x0204
+#define SIRFSOC_CLKC_SDR_CLK_SEL_STAT        0x0208
+#define SIRFSOC_CLKC_VIP_CLK_SEL             0x020c
+#define SIRFSOC_CLKC_VIP_CLK_SEL_STAT        0x0210
+#define SIRFSOC_CLKC_NOCD_CLK_SEL            0x0214
+#define SIRFSOC_CLKC_NOCD_CLK_SEL_STAT       0x0218
+#define SIRFSOC_CLKC_NOCR_CLK_SEL            0x021c
+#define SIRFSOC_CLKC_NOCR_CLK_SEL_STAT       0x0220
+#define SIRFSOC_CLKC_TPIU_CLK_SEL            0x0224
+#define SIRFSOC_CLKC_TPIU_CLK_SEL_STAT       0x0228
+
+#define SIRFSOC_CLKC_ROOT_CLK_EN0_SET        0x022c
+#define SIRFSOC_CLKC_ROOT_CLK_EN0_CLR        0x0230
+#define SIRFSOC_CLKC_ROOT_CLK_EN0_STAT       0x0234
+#define SIRFSOC_CLKC_ROOT_CLK_EN1_SET        0x0238
+#define SIRFSOC_CLKC_ROOT_CLK_EN1_CLR        0x023c
+#define SIRFSOC_CLKC_ROOT_CLK_EN1_STAT       0x0240
+
+#define SIRFSOC_CLKC_LEAF_CLK_EN0_SET        0x0244
+#define SIRFSOC_CLKC_LEAF_CLK_EN0_CLR        0x0248
+#define SIRFSOC_CLKC_LEAF_CLK_EN0_STAT       0x024c
+
+#define SIRFSOC_CLKC_RSTC_A7_SW_RST          0x0308
+
+#define SIRFSOC_CLKC_LEAF_CLK_EN1_SET        0x04a0
+#define SIRFSOC_CLKC_LEAF_CLK_EN2_SET        0x04b8
+#define SIRFSOC_CLKC_LEAF_CLK_EN3_SET        0x04d0
+#define SIRFSOC_CLKC_LEAF_CLK_EN4_SET        0x04e8
+#define SIRFSOC_CLKC_LEAF_CLK_EN5_SET        0x0500
+#define SIRFSOC_CLKC_LEAF_CLK_EN6_SET        0x0518
+#define SIRFSOC_CLKC_LEAF_CLK_EN7_SET        0x0530
+#define SIRFSOC_CLKC_LEAF_CLK_EN8_SET        0x0548
+
+
+static void __iomem *sirfsoc_clk_vbase;
+static struct clk_onecell_data clk_data;
+
+static const struct clk_div_table pll_div_table[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 2, .div = 4 },
+	{ .val = 3, .div = 8 },
+	{ .val = 4, .div = 16 },
+	{ .val = 5, .div = 32 },
+};
+
+struct clk_pll {
+	struct clk_hw hw;
+	u16 regofs;  /* register offset */
+};
+#define to_pllclk(_hw) container_of(_hw, struct clk_pll, hw)
+
+struct clk_dto {
+	struct clk_hw hw;
+	u16 inc_offset;  /* dto increment offset */
+	u16 src_offset;  /* dto src offset */
+};
+#define to_dtoclk(_hw) container_of(_hw, struct clk_dto, hw)
+
+struct clk_unit {
+	struct clk_hw hw;
+	u16 regofs;
+	u16 bit;
+	spinlock_t *lock;
+};
+#define to_unitclk(_hw) container_of(_hw, struct clk_unit, hw)
+
+struct atlas7_div_init_data {
+	const char *div_name;
+	const char *parent_name;
+	const char *gate_name;
+	unsigned long flags;
+	u8 divider_flags;
+	u8 gate_flags;
+	u32 div_offset;
+	u8 shift;
+	u8 width;
+	u32 gate_offset;
+	u8 gate_bit;
+	spinlock_t *lock;
+};
+
+struct atlas7_mux_init_data {
+	const char *mux_name;
+	const char * const *parent_names;
+	u8 parent_num;
+	unsigned long flags;
+	u8 mux_flags;
+	u32 mux_offset;
+	u8 shift;
+	u8 width;
+};
+
+struct atlas7_unit_init_data {
+	u32 index;
+	const char *unit_name;
+	const char *parent_name;
+	unsigned long flags;
+	u32 regofs;
+	u8 bit;
+	spinlock_t *lock;
+};
+
+struct atlas7_reset_desc {
+	const char *name;
+	u32 clk_ofs;
+	u8  clk_bit;
+	u32 rst_ofs;
+	u8  rst_bit;
+	spinlock_t *lock;
+};
+
+static DEFINE_SPINLOCK(cpupll_ctrl1_lock);
+static DEFINE_SPINLOCK(mempll_ctrl1_lock);
+static DEFINE_SPINLOCK(sys0pll_ctrl1_lock);
+static DEFINE_SPINLOCK(sys1pll_ctrl1_lock);
+static DEFINE_SPINLOCK(sys2pll_ctrl1_lock);
+static DEFINE_SPINLOCK(sys3pll_ctrl1_lock);
+static DEFINE_SPINLOCK(usbphy_div_lock);
+static DEFINE_SPINLOCK(btss_div_lock);
+static DEFINE_SPINLOCK(rgmii_div_lock);
+static DEFINE_SPINLOCK(cpu_div_lock);
+static DEFINE_SPINLOCK(sdphy01_div_lock);
+static DEFINE_SPINLOCK(sdphy23_div_lock);
+static DEFINE_SPINLOCK(sdphy45_div_lock);
+static DEFINE_SPINLOCK(sdphy67_div_lock);
+static DEFINE_SPINLOCK(can_div_lock);
+static DEFINE_SPINLOCK(deint_div_lock);
+static DEFINE_SPINLOCK(nand_div_lock);
+static DEFINE_SPINLOCK(disp0_div_lock);
+static DEFINE_SPINLOCK(disp1_div_lock);
+static DEFINE_SPINLOCK(gpu_div_lock);
+static DEFINE_SPINLOCK(gnss_div_lock);
+/* gate register shared */
+static DEFINE_SPINLOCK(share_div_lock);
+static DEFINE_SPINLOCK(root0_gate_lock);
+static DEFINE_SPINLOCK(root1_gate_lock);
+static DEFINE_SPINLOCK(leaf0_gate_lock);
+static DEFINE_SPINLOCK(leaf1_gate_lock);
+static DEFINE_SPINLOCK(leaf2_gate_lock);
+static DEFINE_SPINLOCK(leaf3_gate_lock);
+static DEFINE_SPINLOCK(leaf4_gate_lock);
+static DEFINE_SPINLOCK(leaf5_gate_lock);
+static DEFINE_SPINLOCK(leaf6_gate_lock);
+static DEFINE_SPINLOCK(leaf7_gate_lock);
+static DEFINE_SPINLOCK(leaf8_gate_lock);
+
+static inline unsigned long clkc_readl(unsigned reg)
+{
+	return readl(sirfsoc_clk_vbase + reg);
+}
+
+static inline void clkc_writel(u32 val, unsigned reg)
+{
+	writel(val, sirfsoc_clk_vbase + reg);
+}
+
+/*
+*  ABPLL
+*  integer mode: Fvco = Fin * 2 * NF / NR
+*  Spread Spectrum mode: Fvco = Fin * SSN / NR
+*  SSN = 2^24 / (256 * ((ssdiv >> ssdepth) << ssdepth) + (ssmod << ssdepth))
+*/
+static unsigned long pll_clk_recalc_rate(struct clk_hw *hw,
+	unsigned long parent_rate)
+{
+	unsigned long fin = parent_rate;
+	struct clk_pll *clk = to_pllclk(hw);
+	u64 rate;
+	u32 regctrl0 = clkc_readl(clk->regofs + SIRFSOC_CLKC_MEMPLL_AB_CTRL0 -
+			SIRFSOC_CLKC_MEMPLL_AB_FREQ);
+	u32 regfreq = clkc_readl(clk->regofs);
+	u32 regssc = clkc_readl(clk->regofs + SIRFSOC_CLKC_MEMPLL_AB_SSC -
+			SIRFSOC_CLKC_MEMPLL_AB_FREQ);
+	u32 nr = (regfreq  >> 16 & (BIT(3) - 1)) + 1;
+	u32 nf = (regfreq & (BIT(9) - 1)) + 1;
+	u32 ssdiv = regssc >> 8 & (BIT(12) - 1);
+	u32 ssdepth = regssc >> 20 & (BIT(2) - 1);
+	u32 ssmod = regssc & (BIT(8) - 1);
+
+	if (regctrl0 & SIRFSOC_ABPLL_CTRL0_BYPASS)
+		return fin;
+
+	if (regctrl0 & SIRFSOC_ABPLL_CTRL0_SSEN) {
+		rate = fin;
+		rate *= 1 << 24;
+		do_div(rate, (256 * ((ssdiv >> ssdepth) << ssdepth)
+			+ (ssmod << ssdepth)));
+	} else {
+		rate = 2 * fin;
+		rate *= nf;
+		do_div(rate, nr);
+	}
+	return rate;
+}
+
+static const struct clk_ops ab_pll_ops = {
+	.recalc_rate = pll_clk_recalc_rate,
+};
+
+static const char * const pll_clk_parents[] = {
+	"xin",
+};
+
+static struct clk_init_data clk_cpupll_init = {
+	.name = "cpupll_vco",
+	.ops = &ab_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_cpupll = {
+	.regofs = SIRFSOC_CLKC_CPUPLL_AB_FREQ,
+	.hw = {
+		.init = &clk_cpupll_init,
+	},
+};
+
+static struct clk_init_data clk_mempll_init = {
+	.name = "mempll_vco",
+	.ops = &ab_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_mempll = {
+	.regofs = SIRFSOC_CLKC_MEMPLL_AB_FREQ,
+	.hw = {
+		.init = &clk_mempll_init,
+	},
+};
+
+static struct clk_init_data clk_sys0pll_init = {
+	.name = "sys0pll_vco",
+	.ops = &ab_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_sys0pll = {
+	.regofs = SIRFSOC_CLKC_SYS0PLL_AB_FREQ,
+	.hw = {
+		.init = &clk_sys0pll_init,
+	},
+};
+
+static struct clk_init_data clk_sys1pll_init = {
+	.name = "sys1pll_vco",
+	.ops = &ab_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_sys1pll = {
+	.regofs = SIRFSOC_CLKC_SYS1PLL_AB_FREQ,
+	.hw = {
+		.init = &clk_sys1pll_init,
+	},
+};
+
+static struct clk_init_data clk_sys2pll_init = {
+	.name = "sys2pll_vco",
+	.ops = &ab_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_sys2pll = {
+	.regofs = SIRFSOC_CLKC_SYS2PLL_AB_FREQ,
+	.hw = {
+		.init = &clk_sys2pll_init,
+	},
+};
+
+static struct clk_init_data clk_sys3pll_init = {
+	.name = "sys3pll_vco",
+	.ops = &ab_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_sys3pll = {
+	.regofs = SIRFSOC_CLKC_SYS3PLL_AB_FREQ,
+	.hw = {
+		.init = &clk_sys3pll_init,
+	},
+};
+
+/*
+ *  DTO in clkc, default enable double resolution mode
+ *  double resolution mode:fout = fin * finc / 2^29
+ *  normal mode:fout = fin * finc / 2^28
+ */
+static int dto_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_dto *clk = to_dtoclk(hw);
+	int reg;
+
+	reg = clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_ENA - SIRFSOC_CLKC_AUDIO_DTO_SRC;
+
+	return !!(clkc_readl(reg) & BIT(0));
+}
+
+static int dto_clk_enable(struct clk_hw *hw)
+{
+	u32 val, reg;
+	struct clk_dto *clk = to_dtoclk(hw);
+
+	reg = clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_ENA - SIRFSOC_CLKC_AUDIO_DTO_SRC;
+
+	val = clkc_readl(reg) | BIT(0);
+	clkc_writel(val, reg);
+	return 0;
+}
+
+static void dto_clk_disable(struct clk_hw *hw)
+{
+	u32 val, reg;
+	struct clk_dto *clk = to_dtoclk(hw);
+
+	reg = clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_ENA - SIRFSOC_CLKC_AUDIO_DTO_SRC;
+
+	val = clkc_readl(reg) & ~BIT(0);
+	clkc_writel(val, reg);
+}
+
+static unsigned long dto_clk_recalc_rate(struct clk_hw *hw,
+	unsigned long parent_rate)
+{
+	u64 rate = parent_rate;
+	struct clk_dto *clk = to_dtoclk(hw);
+	u32 finc = clkc_readl(clk->inc_offset);
+	u32 droff = clkc_readl(clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_DROFF - SIRFSOC_CLKC_AUDIO_DTO_SRC);
+
+	rate *= finc;
+	if (droff & BIT(0))
+		/* Double resolution off */
+		do_div(rate, 1 << 28);
+	else
+		do_div(rate, 1 << 29);
+
+	return rate;
+}
+
+static long dto_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+	unsigned long *parent_rate)
+{
+	u64 dividend = rate * (1 << 29);
+
+	do_div(dividend, *parent_rate);
+	dividend *= *parent_rate;
+	do_div(dividend, 1 << 29);
+
+	return dividend;
+}
+
+static int dto_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+	unsigned long parent_rate)
+{
+	u64 dividend = rate * (1 << 29);
+	struct clk_dto *clk = to_dtoclk(hw);
+
+	do_div(dividend, parent_rate);
+	clkc_writel(0, clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_DROFF - SIRFSOC_CLKC_AUDIO_DTO_SRC);
+	clkc_writel(dividend, clk->inc_offset);
+
+	return 0;
+}
+
+static u8 dto_clk_get_parent(struct clk_hw *hw)
+{
+	struct clk_dto *clk = to_dtoclk(hw);
+
+	return clkc_readl(clk->src_offset);
+}
+
+/*
+ *   dto need CLK_SET_PARENT_GATE
+ */
+static int dto_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_dto *clk = to_dtoclk(hw);
+
+	clkc_writel(index, clk->src_offset);
+	return 0;
+}
+
+static const struct clk_ops dto_ops = {
+	.is_enabled = dto_clk_is_enabled,
+	.enable = dto_clk_enable,
+	.disable = dto_clk_disable,
+	.recalc_rate = dto_clk_recalc_rate,
+	.round_rate = dto_clk_round_rate,
+	.set_rate = dto_clk_set_rate,
+	.get_parent = dto_clk_get_parent,
+	.set_parent = dto_clk_set_parent,
+};
+
+/* dto parent clock as syspllvco/clk1 */
+static const char * const audiodto_clk_parents[] = {
+	"sys0pll_clk1",
+	"sys1pll_clk1",
+	"sys3pll_clk1",
+};
+
+static struct clk_init_data clk_audiodto_init = {
+	.name = "audio_dto",
+	.ops = &dto_ops,
+	.parent_names = audiodto_clk_parents,
+	.num_parents = ARRAY_SIZE(audiodto_clk_parents),
+};
+
+static struct clk_dto clk_audio_dto = {
+	.inc_offset = SIRFSOC_CLKC_AUDIO_DTO_INC,
+	.src_offset = SIRFSOC_CLKC_AUDIO_DTO_SRC,
+	.hw = {
+		.init = &clk_audiodto_init,
+	},
+};
+
+static const char * const disp0dto_clk_parents[] = {
+	"sys0pll_clk1",
+	"sys1pll_clk1",
+	"sys3pll_clk1",
+};
+
+static struct clk_init_data clk_disp0dto_init = {
+	.name = "disp0_dto",
+	.ops = &dto_ops,
+	.parent_names = disp0dto_clk_parents,
+	.num_parents = ARRAY_SIZE(disp0dto_clk_parents),
+};
+
+static struct clk_dto clk_disp0_dto = {
+	.inc_offset = SIRFSOC_CLKC_DISP0_DTO_INC,
+	.src_offset = SIRFSOC_CLKC_DISP0_DTO_SRC,
+	.hw = {
+		.init = &clk_disp0dto_init,
+	},
+};
+
+static const char * const disp1dto_clk_parents[] = {
+	"sys0pll_clk1",
+	"sys1pll_clk1",
+	"sys3pll_clk1",
+};
+
+static struct clk_init_data clk_disp1dto_init = {
+	.name = "disp1_dto",
+	.ops = &dto_ops,
+	.parent_names = disp1dto_clk_parents,
+	.num_parents = ARRAY_SIZE(disp1dto_clk_parents),
+};
+
+static struct clk_dto clk_disp1_dto = {
+	.inc_offset = SIRFSOC_CLKC_DISP1_DTO_INC,
+	.src_offset = SIRFSOC_CLKC_DISP1_DTO_SRC,
+	.hw = {
+		.init = &clk_disp1dto_init,
+	},
+};
+
+static struct atlas7_div_init_data divider_list[] __initdata = {
+	/* div_name, parent_name, gate_name, clk_flag, divider_flag, gate_flag, div_offset, shift, wdith, gate_offset, bit_enable, lock */
+	{ "sys0pll_qa1", "sys0pll_fixdiv", "sys0pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 0, &usbphy_div_lock },
+	{ "sys1pll_qa1", "sys1pll_fixdiv", "sys1pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 4, &usbphy_div_lock },
+	{ "sys2pll_qa1", "sys2pll_fixdiv", "sys2pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 8, &usbphy_div_lock },
+	{ "sys3pll_qa1", "sys3pll_fixdiv", "sys3pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 12, &usbphy_div_lock },
+	{ "sys0pll_qa2", "sys0pll_fixdiv", "sys0pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 0, &btss_div_lock },
+	{ "sys1pll_qa2", "sys1pll_fixdiv", "sys1pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 4, &btss_div_lock },
+	{ "sys2pll_qa2", "sys2pll_fixdiv", "sys2pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 8, &btss_div_lock },
+	{ "sys3pll_qa2", "sys3pll_fixdiv", "sys3pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 12, &btss_div_lock },
+	{ "sys0pll_qa3", "sys0pll_fixdiv", "sys0pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 0, &rgmii_div_lock },
+	{ "sys1pll_qa3", "sys1pll_fixdiv", "sys1pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 4, &rgmii_div_lock },
+	{ "sys2pll_qa3", "sys2pll_fixdiv", "sys2pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 8, &rgmii_div_lock },
+	{ "sys3pll_qa3", "sys3pll_fixdiv", "sys3pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 12, &rgmii_div_lock },
+	{ "sys0pll_qa4", "sys0pll_fixdiv", "sys0pll_a4", 0, 0, 0, SIRFSOC_CLKC_CPU_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_CPU_CLKDIV_ENA, 0, &cpu_div_lock },
+	{ "sys1pll_qa4", "sys1pll_fixdiv", "sys1pll_a4", 0, 0, CLK_IGNORE_UNUSED, SIRFSOC_CLKC_CPU_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_CPU_CLKDIV_ENA, 4, &cpu_div_lock },
+	{ "sys0pll_qa5", "sys0pll_fixdiv", "sys0pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 0, &sdphy01_div_lock },
+	{ "sys1pll_qa5", "sys1pll_fixdiv", "sys1pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 4, &sdphy01_div_lock },
+	{ "sys2pll_qa5", "sys2pll_fixdiv", "sys2pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 8, &sdphy01_div_lock },
+	{ "sys3pll_qa5", "sys3pll_fixdiv", "sys3pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 12, &sdphy01_div_lock },
+	{ "sys0pll_qa6", "sys0pll_fixdiv", "sys0pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 0, &sdphy23_div_lock },
+	{ "sys1pll_qa6", "sys1pll_fixdiv", "sys1pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 4, &sdphy23_div_lock },
+	{ "sys2pll_qa6", "sys2pll_fixdiv", "sys2pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 8, &sdphy23_div_lock },
+	{ "sys3pll_qa6", "sys3pll_fixdiv", "sys3pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 12, &sdphy23_div_lock },
+	{ "sys0pll_qa7", "sys0pll_fixdiv", "sys0pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 0, &sdphy45_div_lock },
+	{ "sys1pll_qa7", "sys1pll_fixdiv", "sys1pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 4, &sdphy45_div_lock },
+	{ "sys2pll_qa7", "sys2pll_fixdiv", "sys2pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 8, &sdphy45_div_lock },
+	{ "sys3pll_qa7", "sys3pll_fixdiv", "sys3pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 12, &sdphy45_div_lock },
+	{ "sys0pll_qa8", "sys0pll_fixdiv", "sys0pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 0, &sdphy67_div_lock },
+	{ "sys1pll_qa8", "sys1pll_fixdiv", "sys1pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 4, &sdphy67_div_lock },
+	{ "sys2pll_qa8", "sys2pll_fixdiv", "sys2pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 8, &sdphy67_div_lock },
+	{ "sys3pll_qa8", "sys3pll_fixdiv", "sys3pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 12, &sdphy67_div_lock },
+	{ "sys0pll_qa9", "sys0pll_fixdiv", "sys0pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 0, &can_div_lock },
+	{ "sys1pll_qa9", "sys1pll_fixdiv", "sys1pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 4, &can_div_lock },
+	{ "sys2pll_qa9", "sys2pll_fixdiv", "sys2pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 8, &can_div_lock },
+	{ "sys3pll_qa9", "sys3pll_fixdiv", "sys3pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 12, &can_div_lock },
+	{ "sys0pll_qa10", "sys0pll_fixdiv", "sys0pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 0, &deint_div_lock },
+	{ "sys1pll_qa10", "sys1pll_fixdiv", "sys1pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 4, &deint_div_lock },
+	{ "sys2pll_qa10", "sys2pll_fixdiv", "sys2pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 8, &deint_div_lock },
+	{ "sys3pll_qa10", "sys3pll_fixdiv", "sys3pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 12, &deint_div_lock },
+	{ "sys0pll_qa11", "sys0pll_fixdiv", "sys0pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 0, &nand_div_lock },
+	{ "sys1pll_qa11", "sys1pll_fixdiv", "sys1pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 4, &nand_div_lock },
+	{ "sys2pll_qa11", "sys2pll_fixdiv", "sys2pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 8, &nand_div_lock },
+	{ "sys3pll_qa11", "sys3pll_fixdiv", "sys3pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 12, &nand_div_lock },
+	{ "sys0pll_qa12", "sys0pll_fixdiv", "sys0pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 0, &disp0_div_lock },
+	{ "sys1pll_qa12", "sys1pll_fixdiv", "sys1pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 4, &disp0_div_lock },
+	{ "sys2pll_qa12", "sys2pll_fixdiv", "sys2pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 8, &disp0_div_lock },
+	{ "sys3pll_qa12", "sys3pll_fixdiv", "sys3pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 12, &disp0_div_lock },
+	{ "sys0pll_qa13", "sys0pll_fixdiv", "sys0pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 0, &disp1_div_lock },
+	{ "sys1pll_qa13", "sys1pll_fixdiv", "sys1pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 4, &disp1_div_lock },
+	{ "sys2pll_qa13", "sys2pll_fixdiv", "sys2pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 8, &disp1_div_lock },
+	{ "sys3pll_qa13", "sys3pll_fixdiv", "sys3pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 12, &disp1_div_lock },
+	{ "sys0pll_qa14", "sys0pll_fixdiv", "sys0pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 0, &gpu_div_lock },
+	{ "sys1pll_qa14", "sys1pll_fixdiv", "sys1pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 4, &gpu_div_lock },
+	{ "sys2pll_qa14", "sys2pll_fixdiv", "sys2pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 8, &gpu_div_lock },
+	{ "sys3pll_qa14", "sys3pll_fixdiv", "sys3pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 12, &gpu_div_lock },
+	{ "sys0pll_qa15", "sys0pll_fixdiv", "sys0pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 0, &gnss_div_lock },
+	{ "sys1pll_qa15", "sys1pll_fixdiv", "sys1pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 4, &gnss_div_lock },
+	{ "sys2pll_qa15", "sys2pll_fixdiv", "sys2pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 8, &gnss_div_lock },
+	{ "sys3pll_qa15", "sys3pll_fixdiv", "sys3pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 12, &gnss_div_lock },
+	{ "sys1pll_qa18", "sys1pll_fixdiv", "sys1pll_a18", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 24, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 12, &share_div_lock },
+	{ "sys1pll_qa19", "sys1pll_fixdiv", "sys1pll_a19", 0, 0, CLK_IGNORE_UNUSED, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 16, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 8, &share_div_lock },
+	{ "sys1pll_qa20", "sys1pll_fixdiv", "sys1pll_a20", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 8, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 4, &share_div_lock },
+	{ "sys2pll_qa20", "sys2pll_fixdiv", "sys2pll_a20", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 0, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 0, &share_div_lock },
+	{ "sys1pll_qa17", "sys1pll_fixdiv", "sys1pll_a17", 0, 0, CLK_IGNORE_UNUSED, SIRFSOC_CLKC_SHARED_DIVIDER_CFG1, 8, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 20, &share_div_lock },
+	{ "sys0pll_qa20", "sys0pll_fixdiv", "sys0pll_a20", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG1, 0, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 16, &share_div_lock },
+};
+
+static const char * const i2s_clk_parents[] = {
+	"xin",
+	"xinw",
+	"audio_dto",
+	/* "pwm_i2s01" */
+};
+
+static const char * const usbphy_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a1",
+	"sys1pll_a1",
+	"sys2pll_a1",
+	"sys3pll_a1",
+};
+
+static const char * const btss_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a2",
+	"sys1pll_a2",
+	"sys2pll_a2",
+	"sys3pll_a2",
+};
+
+static const char * const rgmii_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a3",
+	"sys1pll_a3",
+	"sys2pll_a3",
+	"sys3pll_a3",
+};
+
+static const char * const cpu_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a4",
+	"sys1pll_a4",
+	"cpupll_clk1",
+};
+
+static const char * const sdphy01_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a5",
+	"sys1pll_a5",
+	"sys2pll_a5",
+	"sys3pll_a5",
+};
+
+static const char * const sdphy23_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a6",
+	"sys1pll_a6",
+	"sys2pll_a6",
+	"sys3pll_a6",
+};
+
+static const char * const sdphy45_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a7",
+	"sys1pll_a7",
+	"sys2pll_a7",
+	"sys3pll_a7",
+};
+
+static const char * const sdphy67_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a8",
+	"sys1pll_a8",
+	"sys2pll_a8",
+	"sys3pll_a8",
+};
+
+static const char * const can_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a9",
+	"sys1pll_a9",
+	"sys2pll_a9",
+	"sys3pll_a9",
+};
+
+static const char * const deint_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a10",
+	"sys1pll_a10",
+	"sys2pll_a10",
+	"sys3pll_a10",
+};
+
+static const char * const nand_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a11",
+	"sys1pll_a11",
+	"sys2pll_a11",
+	"sys3pll_a11",
+};
+
+static const char * const disp0_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a12",
+	"sys1pll_a12",
+	"sys2pll_a12",
+	"sys3pll_a12",
+	"disp0_dto",
+};
+
+static const char * const disp1_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a13",
+	"sys1pll_a13",
+	"sys2pll_a13",
+	"sys3pll_a13",
+	"disp1_dto",
+};
+
+static const char * const gpu_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a14",
+	"sys1pll_a14",
+	"sys2pll_a14",
+	"sys3pll_a14",
+};
+
+static const char * const gnss_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys0pll_a15",
+	"sys1pll_a15",
+	"sys2pll_a15",
+	"sys3pll_a15",
+};
+
+static const char * const sys_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const io_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const g2d_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const jpenc_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const vdec_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const gmac_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const usb_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const kas_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const sec_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const sdr_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const vip_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const nocd_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const nocr_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static const char * const tpiu_clk_parents[] = {
+	"xin",
+	"xinw",
+	"sys2pll_a20",
+	"sys1pll_a20",
+	"sys1pll_a19",
+	"sys1pll_a18",
+	"sys0pll_a20",
+	"sys1pll_a17",
+};
+
+static struct atlas7_mux_init_data mux_list[] __initdata = {
+	/* mux_name, parent_names, parent_num, flags, mux_flags, mux_offset, shift, width */
+	{ "i2s_mux", i2s_clk_parents, ARRAY_SIZE(i2s_clk_parents), 0, 0, SIRFSOC_CLKC_I2S_CLK_SEL, 0, 2 },
+	{ "usbphy_mux", usbphy_clk_parents, ARRAY_SIZE(usbphy_clk_parents), 0, 0, SIRFSOC_CLKC_I2S_CLK_SEL, 0, 3 },
+	{ "btss_mux", btss_clk_parents, ARRAY_SIZE(btss_clk_parents), 0, 0, SIRFSOC_CLKC_BTSS_CLK_SEL, 0, 3 },
+	{ "rgmii_mux", rgmii_clk_parents, ARRAY_SIZE(rgmii_clk_parents), 0, 0, SIRFSOC_CLKC_RGMII_CLK_SEL, 0, 3 },
+	{ "cpu_mux", cpu_clk_parents, ARRAY_SIZE(cpu_clk_parents), 0, 0, SIRFSOC_CLKC_CPU_CLK_SEL, 0, 3 },
+	{ "sdphy01_mux", sdphy01_clk_parents, ARRAY_SIZE(sdphy01_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY01_CLK_SEL, 0, 3 },
+	{ "sdphy23_mux", sdphy23_clk_parents, ARRAY_SIZE(sdphy23_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY23_CLK_SEL, 0, 3 },
+	{ "sdphy45_mux", sdphy45_clk_parents, ARRAY_SIZE(sdphy45_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY45_CLK_SEL, 0, 3 },
+	{ "sdphy67_mux", sdphy67_clk_parents, ARRAY_SIZE(sdphy67_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY67_CLK_SEL, 0, 3 },
+	{ "can_mux", can_clk_parents, ARRAY_SIZE(can_clk_parents), 0, 0, SIRFSOC_CLKC_CAN_CLK_SEL, 0, 3 },
+	{ "deint_mux", deint_clk_parents, ARRAY_SIZE(deint_clk_parents), 0, 0, SIRFSOC_CLKC_DEINT_CLK_SEL, 0, 3 },
+	{ "nand_mux", nand_clk_parents, ARRAY_SIZE(nand_clk_parents), 0, 0, SIRFSOC_CLKC_NAND_CLK_SEL, 0, 3 },
+	{ "disp0_mux", disp0_clk_parents, ARRAY_SIZE(disp0_clk_parents), 0, 0, SIRFSOC_CLKC_DISP0_CLK_SEL, 0, 3 },
+	{ "disp1_mux", disp1_clk_parents, ARRAY_SIZE(disp1_clk_parents), 0, 0, SIRFSOC_CLKC_DISP1_CLK_SEL, 0, 3 },
+	{ "gpu_mux", gpu_clk_parents, ARRAY_SIZE(gpu_clk_parents), 0, 0, SIRFSOC_CLKC_GPU_CLK_SEL, 0, 3 },
+	{ "gnss_mux", gnss_clk_parents, ARRAY_SIZE(gnss_clk_parents), 0, 0, SIRFSOC_CLKC_GNSS_CLK_SEL, 0, 3 },
+	{ "sys_mux", sys_clk_parents, ARRAY_SIZE(sys_clk_parents), 0, 0, SIRFSOC_CLKC_SYS_CLK_SEL, 0, 3 },
+	{ "io_mux", io_clk_parents, ARRAY_SIZE(io_clk_parents), 0, 0, SIRFSOC_CLKC_IO_CLK_SEL, 0, 3 },
+	{ "g2d_mux", g2d_clk_parents, ARRAY_SIZE(g2d_clk_parents), 0, 0, SIRFSOC_CLKC_G2D_CLK_SEL, 0, 3 },
+	{ "jpenc_mux", jpenc_clk_parents, ARRAY_SIZE(jpenc_clk_parents), 0, 0, SIRFSOC_CLKC_JPENC_CLK_SEL, 0, 3 },
+	{ "vdec_mux", vdec_clk_parents, ARRAY_SIZE(vdec_clk_parents), 0, 0, SIRFSOC_CLKC_VDEC_CLK_SEL, 0, 3 },
+	{ "gmac_mux", gmac_clk_parents, ARRAY_SIZE(gmac_clk_parents), 0, 0, SIRFSOC_CLKC_GMAC_CLK_SEL, 0, 3 },
+	{ "usb_mux", usb_clk_parents, ARRAY_SIZE(usb_clk_parents), 0, 0, SIRFSOC_CLKC_USB_CLK_SEL, 0, 3 },
+	{ "kas_mux", kas_clk_parents, ARRAY_SIZE(kas_clk_parents), 0, 0, SIRFSOC_CLKC_KAS_CLK_SEL, 0, 3 },
+	{ "sec_mux", sec_clk_parents, ARRAY_SIZE(sec_clk_parents), 0, 0, SIRFSOC_CLKC_SEC_CLK_SEL, 0, 3 },
+	{ "sdr_mux", sdr_clk_parents, ARRAY_SIZE(sdr_clk_parents), 0, 0, SIRFSOC_CLKC_SDR_CLK_SEL, 0, 3 },
+	{ "vip_mux", vip_clk_parents, ARRAY_SIZE(vip_clk_parents), 0, 0, SIRFSOC_CLKC_VIP_CLK_SEL, 0, 3 },
+	{ "nocd_mux", nocd_clk_parents, ARRAY_SIZE(nocd_clk_parents), 0, 0, SIRFSOC_CLKC_NOCD_CLK_SEL, 0, 3 },
+	{ "nocr_mux", nocr_clk_parents, ARRAY_SIZE(nocr_clk_parents), 0, 0, SIRFSOC_CLKC_NOCR_CLK_SEL, 0, 3 },
+	{ "tpiu_mux", tpiu_clk_parents, ARRAY_SIZE(tpiu_clk_parents), 0, 0, SIRFSOC_CLKC_TPIU_CLK_SEL, 0, 3 },
+};
+
+	/* new unit should add start from the tail of list */
+static struct atlas7_unit_init_data unit_list[] __initdata = {
+	/* unit_name, parent_name, flags, regofs, bit, lock */
+	{ 0, "audmscm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 0, &root0_gate_lock },
+	{ 1, "gnssm_gnss", "gnss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 1, &root0_gate_lock },
+	{ 2, "gpum_gpu", "gpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 2, &root0_gate_lock },
+	{ 3, "mediam_g2d", "g2d_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 3, &root0_gate_lock },
+	{ 4, "mediam_jpenc", "jpenc_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 4, &root0_gate_lock },
+	{ 5, "vdifm_disp0", "disp0_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 5, &root0_gate_lock },
+	{ 6, "vdifm_disp1", "disp1_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 6, &root0_gate_lock },
+	{ 7, "audmscm_i2s", "i2s_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 8, &root0_gate_lock },
+	{ 8, "audmscm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 11, &root0_gate_lock },
+	{ 9, "vdifm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 12, &root0_gate_lock },
+	{ 10, "gnssm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 13, &root0_gate_lock },
+	{ 11, "mediam_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 14, &root0_gate_lock },
+	{ 12, "btm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 17, &root0_gate_lock },
+	{ 13, "mediam_sdphy01", "sdphy01_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 18, &root0_gate_lock },
+	{ 14, "vdifm_sdphy23", "sdphy23_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 19, &root0_gate_lock },
+	{ 15, "vdifm_sdphy45", "sdphy45_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 20, &root0_gate_lock },
+	{ 16, "vdifm_sdphy67", "sdphy67_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 21, &root0_gate_lock },
+	{ 17, "audmscm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 22, &root0_gate_lock },
+	{ 18, "mediam_nand", "nand_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 27, &root0_gate_lock },
+	{ 19, "gnssm_sec", "sec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 28, &root0_gate_lock },
+	{ 20, "cpum_cpu", "cpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 29, &root0_gate_lock },
+	{ 21, "gnssm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 30, &root0_gate_lock },
+	{ 22, "vdifm_vip", "vip_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 31, &root0_gate_lock },
+	{ 23, "btm_btss", "btss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 0, &root1_gate_lock },
+	{ 24, "mediam_usbphy", "usbphy_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 1, &root1_gate_lock },
+	{ 25, "rtcm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 2, &root1_gate_lock },
+	{ 26, "audmscm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 3, &root1_gate_lock },
+	{ 27, "vdifm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 4, &root1_gate_lock },
+	{ 28, "gnssm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 5, &root1_gate_lock },
+	{ 29, "mediam_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 6, &root1_gate_lock },
+	{ 30, "cpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 8, &root1_gate_lock },
+	{ 31, "gpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 9, &root1_gate_lock },
+	{ 32, "audmscm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 11, &root1_gate_lock },
+	{ 33, "vdifm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 12, &root1_gate_lock },
+	{ 34, "gnssm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 13, &root1_gate_lock },
+	{ 35, "mediam_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 14, &root1_gate_lock },
+	{ 36, "ddrm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 15, &root1_gate_lock },
+	{ 37, "cpum_tpiu", "tpiu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 16, &root1_gate_lock },
+	{ 38, "gpum_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 17, &root1_gate_lock },
+	{ 39, "gnssm_rgmii", "rgmii_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 20, &root1_gate_lock },
+	{ 40, "mediam_vdec", "vdec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 21, &root1_gate_lock },
+	{ 41, "gpum_sdr", "sdr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 22, &root1_gate_lock },
+	{ 42, "vdifm_deint", "deint_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 23, &root1_gate_lock },
+	{ 43, "gnssm_can", "can_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 26, &root1_gate_lock },
+	{ 44, "mediam_usb", "usb_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 28, &root1_gate_lock },
+	{ 45, "gnssm_gmac", "gmac_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 29, &root1_gate_lock },
+	{ 46, "cvd_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 0, &leaf1_gate_lock },
+	{ 47, "timer_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 1, &leaf1_gate_lock },
+	{ 48, "pulse_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 2, &leaf1_gate_lock },
+	{ 49, "tsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 3, &leaf1_gate_lock },
+	{ 50, "tsc_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 21, &leaf1_gate_lock },
+	{ 51, "ioctop_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 4, &leaf1_gate_lock },
+	{ 52, "rsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 5, &leaf1_gate_lock },
+	{ 53, "dvm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 6, &leaf1_gate_lock },
+	{ 54, "lvds_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 7, &leaf1_gate_lock },
+	{ 55, "kas_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 8, &leaf1_gate_lock },
+	{ 56, "ac97_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 9, &leaf1_gate_lock },
+	{ 57, "usp0_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 10, &leaf1_gate_lock },
+	{ 58, "usp1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 11, &leaf1_gate_lock },
+	{ 59, "usp2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 12, &leaf1_gate_lock },
+	{ 60, "dmac2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 13, &leaf1_gate_lock },
+	{ 61, "dmac3_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 14, &leaf1_gate_lock },
+	{ 62, "audioif_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 15, &leaf1_gate_lock },
+	{ 63, "i2s1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 17, &leaf1_gate_lock },
+	{ 64, "thaudmscm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 22, &leaf1_gate_lock },
+	{ 65, "analogtest_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 23, &leaf1_gate_lock },
+	{ 66, "sys2pci_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 0, &leaf2_gate_lock },
+	{ 67, "pciarb_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 1, &leaf2_gate_lock },
+	{ 68, "pcicopy_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 2, &leaf2_gate_lock },
+	{ 69, "rom_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 3, &leaf2_gate_lock },
+	{ 70, "sdio23_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 4, &leaf2_gate_lock },
+	{ 71, "sdio45_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 5, &leaf2_gate_lock },
+	{ 72, "sdio67_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 6, &leaf2_gate_lock },
+	{ 73, "vip1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 7, &leaf2_gate_lock },
+	{ 74, "vip1_vip", "vdifm_vip", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 16, &leaf2_gate_lock },
+	{ 75, "sdio23_sdphy23", "vdifm_sdphy23", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 8, &leaf2_gate_lock },
+	{ 76, "sdio45_sdphy45", "vdifm_sdphy45", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 9, &leaf2_gate_lock },
+	{ 77, "sdio67_sdphy67", "vdifm_sdphy67", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 10, &leaf2_gate_lock },
+	{ 78, "vpp0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 11, &leaf2_gate_lock },
+	{ 79, "lcd0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 12, &leaf2_gate_lock },
+	{ 80, "vpp1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 13, &leaf2_gate_lock },
+	{ 81, "lcd1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 14, &leaf2_gate_lock },
+	{ 82, "dcu_deint", "vdifm_deint", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 15, &leaf2_gate_lock },
+	{ 83, "vdifm_dapa_r_nocr", "vdifm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 17, &leaf2_gate_lock },
+	{ 84, "gpio1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 18, &leaf2_gate_lock },
+	{ 85, "thvdifm_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 19, &leaf2_gate_lock },
+	{ 86, "gmac_rgmii", "gnssm_rgmii", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 0, &leaf3_gate_lock },
+	{ 87, "gmac_gmac", "gnssm_gmac", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 1, &leaf3_gate_lock },
+	{ 88, "uart1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 2, &leaf3_gate_lock },
+	{ 89, "dmac0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 3, &leaf3_gate_lock },
+	{ 90, "uart0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 4, &leaf3_gate_lock },
+	{ 91, "uart2_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 5, &leaf3_gate_lock },
+	{ 92, "uart3_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 6, &leaf3_gate_lock },
+	{ 93, "uart4_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 7, &leaf3_gate_lock },
+	{ 94, "uart5_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 8, &leaf3_gate_lock },
+	{ 95, "spi1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 9, &leaf3_gate_lock },
+	{ 96, "gnss_gnss", "gnssm_gnss", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 10, &leaf3_gate_lock },
+	{ 97, "canbus1_can", "gnssm_can", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 12, &leaf3_gate_lock },
+	{ 98, "ccsec_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 15, &leaf3_gate_lock },
+	{ 99,  "ccpub_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 16, &leaf3_gate_lock },
+	{ 100, "gnssm_dapa_r_nocr", "gnssm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 13, &leaf3_gate_lock },
+	{ 101, "thgnssm_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 14, &leaf3_gate_lock },
+	{ 102, "media_vdec", "mediam_vdec", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 0, &leaf4_gate_lock },
+	{ 103, "media_jpenc", "mediam_jpenc", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 1, &leaf4_gate_lock },
+	{ 104, "g2d_g2d", "mediam_g2d", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 2, &leaf4_gate_lock },
+	{ 105, "i2c0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 3, &leaf4_gate_lock },
+	{ 106, "i2c1_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 4, &leaf4_gate_lock },
+	{ 107, "gpio0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 5, &leaf4_gate_lock },
+	{ 108, "nand_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 6, &leaf4_gate_lock },
+	{ 109, "sdio01_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 7, &leaf4_gate_lock },
+	{ 110, "sys2pci2_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 8, &leaf4_gate_lock },
+	{ 111, "sdio01_sdphy01", "mediam_sdphy01", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 9, &leaf4_gate_lock },
+	{ 112, "nand_nand", "mediam_nand", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 10, &leaf4_gate_lock },
+	{ 113, "usb0_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 11, &leaf4_gate_lock },
+	{ 114, "usb1_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 12, &leaf4_gate_lock },
+	{ 115, "usbphy0_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 13, &leaf4_gate_lock },
+	{ 116, "usbphy1_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 14, &leaf4_gate_lock },
+	{ 117, "thmediam_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 15, &leaf4_gate_lock },
+	{ 118, "memc_mem", "mempll_clk1", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 0, &leaf5_gate_lock },
+	{ 119, "dapa_mem", "mempll_clk1", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 1, &leaf5_gate_lock },
+	{ 120, "nocddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 2, &leaf5_gate_lock },
+	{ 121, "thddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 3, &leaf5_gate_lock },
+	{ 122, "spram1_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 0, &leaf6_gate_lock },
+	{ 123, "spram2_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 1, &leaf6_gate_lock },
+	{ 124, "coresight_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 2, &leaf6_gate_lock },
+	{ 125, "thcpum_cpudiv4", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 3, &leaf6_gate_lock },
+	{ 126, "graphic_gpu", "gpum_gpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 0, &leaf7_gate_lock },
+	{ 127, "vss_sdr", "gpum_sdr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 1, &leaf7_gate_lock },
+	{ 128, "thgpum_nocr", "gpum_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 2, &leaf7_gate_lock },
+	{ 129, "a7ca_btss", "btm_btss", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 1, &leaf8_gate_lock },
+	{ 130, "dmac4_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 2, &leaf8_gate_lock },
+	{ 131, "uart6_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 3, &leaf8_gate_lock },
+	{ 132, "usp3_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 4, &leaf8_gate_lock },
+	{ 133, "a7ca_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 5, &leaf8_gate_lock },
+	{ 134, "noc_btm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 6, &leaf8_gate_lock },
+	{ 135, "thbtm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 7, &leaf8_gate_lock },
+	{ 136, "btslow", "xinw_fixdiv_btslow", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 25, &root1_gate_lock },
+	{ 137, "a7ca_btslow", "btslow", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 0, &leaf8_gate_lock },
+};
+
+static struct clk *atlas7_clks[ARRAY_SIZE(unit_list)];
+
+static int unit_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_unit *clk = to_unitclk(hw);
+	u32 reg;
+
+	reg = clk->regofs + SIRFSOC_CLKC_ROOT_CLK_EN0_STAT - SIRFSOC_CLKC_ROOT_CLK_EN0_SET;
+
+	return !!(clkc_readl(reg) & BIT(clk->bit));
+}
+
+static int unit_clk_enable(struct clk_hw *hw)
+{
+	u32 reg;
+	struct clk_unit *clk = to_unitclk(hw);
+	unsigned long flags;
+
+	reg = clk->regofs;
+
+	spin_lock_irqsave(clk->lock, flags);
+	clkc_writel(BIT(clk->bit), reg);
+	spin_unlock_irqrestore(clk->lock, flags);
+	return 0;
+}
+
+static void unit_clk_disable(struct clk_hw *hw)
+{
+	u32  reg;
+	struct clk_unit *clk = to_unitclk(hw);
+	unsigned long flags;
+
+	reg = clk->regofs + SIRFSOC_CLKC_ROOT_CLK_EN0_CLR - SIRFSOC_CLKC_ROOT_CLK_EN0_SET;
+
+	spin_lock_irqsave(clk->lock, flags);
+	clkc_writel(BIT(clk->bit), reg);
+	spin_unlock_irqrestore(clk->lock, flags);
+}
+
+static const struct clk_ops unit_clk_ops = {
+	.is_enabled = unit_clk_is_enabled,
+	.enable = unit_clk_enable,
+	.disable = unit_clk_disable,
+};
+
+static struct clk * __init
+atlas7_unit_clk_register(struct device *dev, const char *name,
+		 const char * const parent_name, unsigned long flags,
+		 u32 regofs, u8 bit, spinlock_t *lock)
+{
+	struct clk *clk;
+	struct clk_unit *unit;
+	struct clk_init_data init;
+
+	unit = kzalloc(sizeof(*unit), GFP_KERNEL);
+	if (!unit)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+	init.ops = &unit_clk_ops;
+	init.flags = flags;
+
+	unit->hw.init = &init;
+	unit->regofs = regofs;
+	unit->bit = bit;
+	unit->lock = lock;
+
+	clk = clk_register(dev, &unit->hw);
+	if (IS_ERR(clk))
+		kfree(unit);
+
+	return clk;
+}
+
+static struct atlas7_reset_desc atlas7_reset_unit[] = {
+	{ "PWM", 0x0244, 0, 0x0320, 0, &leaf0_gate_lock }, /* 0-5 */
+	{ "THCGUM", 0x0244, 3, 0x0320, 1, &leaf0_gate_lock },
+	{ "CVD", 0x04A0, 0, 0x032C, 0, &leaf1_gate_lock },
+	{ "TIMER", 0x04A0, 1, 0x032C, 1, &leaf1_gate_lock },
+	{ "PULSEC", 0x04A0, 2, 0x032C, 2, &leaf1_gate_lock },
+	{ "TSC", 0x04A0, 3, 0x032C, 3, &leaf1_gate_lock },
+	{ "IOCTOP", 0x04A0, 4, 0x032C, 4, &leaf1_gate_lock }, /* 6-10 */
+	{ "RSC", 0x04A0, 5, 0x032C, 5, &leaf1_gate_lock },
+	{ "DVM", 0x04A0, 6, 0x032C, 6, &leaf1_gate_lock },
+	{ "LVDS", 0x04A0, 7, 0x032C, 7, &leaf1_gate_lock },
+	{ "KAS", 0x04A0, 8, 0x032C, 8, &leaf1_gate_lock },
+	{ "AC97", 0x04A0, 9, 0x032C, 9, &leaf1_gate_lock }, /* 11-15 */
+	{ "USP0", 0x04A0, 10, 0x032C, 10, &leaf1_gate_lock },
+	{ "USP1", 0x04A0, 11, 0x032C, 11, &leaf1_gate_lock },
+	{ "USP2", 0x04A0, 12, 0x032C, 12, &leaf1_gate_lock },
+	{ "DMAC2", 0x04A0, 13, 0x032C, 13, &leaf1_gate_lock },
+	{ "DMAC3", 0x04A0, 14, 0x032C, 14, &leaf1_gate_lock }, /* 16-20 */
+	{ "AUDIO", 0x04A0, 15, 0x032C, 15, &leaf1_gate_lock },
+	{ "I2S1", 0x04A0, 17, 0x032C, 16, &leaf1_gate_lock },
+	{ "PMU_AUDIO", 0x04A0, 22, 0x032C, 17, &leaf1_gate_lock },
+	{ "THAUDMSCM", 0x04A0, 23, 0x032C, 18, &leaf1_gate_lock },
+	{ "SYS2PCI", 0x04B8, 0, 0x0338, 0, &leaf2_gate_lock }, /* 21-25 */
+	{ "PCIARB", 0x04B8, 1, 0x0338, 1, &leaf2_gate_lock },
+	{ "PCICOPY", 0x04B8, 2, 0x0338, 2, &leaf2_gate_lock },
+	{ "ROM", 0x04B8, 3, 0x0338, 3, &leaf2_gate_lock },
+	{ "SDIO23", 0x04B8, 4, 0x0338, 4, &leaf2_gate_lock },
+	{ "SDIO45", 0x04B8, 5, 0x0338, 5, &leaf2_gate_lock }, /* 26-30 */
+	{ "SDIO67", 0x04B8, 6, 0x0338, 6, &leaf2_gate_lock },
+	{ "VIP1", 0x04B8, 7, 0x0338, 7, &leaf2_gate_lock },
+	{ "VPP0", 0x04B8, 11, 0x0338, 8, &leaf2_gate_lock },
+	{ "LCD0", 0x04B8, 12, 0x0338, 9, &leaf2_gate_lock },
+	{ "VPP1", 0x04B8, 13, 0x0338, 10, &leaf2_gate_lock }, /* 31-35 */
+	{ "LCD1", 0x04B8, 14, 0x0338, 11, &leaf2_gate_lock },
+	{ "DCU", 0x04B8, 15, 0x0338, 12, &leaf2_gate_lock },
+	{ "GPIO", 0x04B8, 18, 0x0338, 13, &leaf2_gate_lock },
+	{ "DAPA_VDIFM", 0x04B8, 17, 0x0338, 15, &leaf2_gate_lock },
+	{ "THVDIFM", 0x04B8, 19, 0x0338, 16, &leaf2_gate_lock }, /* 36-40 */
+	{ "RGMII", 0x04D0, 0, 0x0344, 0, &leaf3_gate_lock },
+	{ "GMAC", 0x04D0, 1, 0x0344, 1, &leaf3_gate_lock },
+	{ "UART1", 0x04D0, 2, 0x0344, 2, &leaf3_gate_lock },
+	{ "DMAC0", 0x04D0, 3, 0x0344, 3, &leaf3_gate_lock },
+	{ "UART0", 0x04D0, 4, 0x0344, 4, &leaf3_gate_lock }, /* 41-45 */
+	{ "UART2", 0x04D0, 5, 0x0344, 5, &leaf3_gate_lock },
+	{ "UART3", 0x04D0, 6, 0x0344, 6, &leaf3_gate_lock },
+	{ "UART4", 0x04D0, 7, 0x0344, 7, &leaf3_gate_lock },
+	{ "UART5", 0x04D0, 8, 0x0344, 8, &leaf3_gate_lock },
+	{ "SPI1", 0x04D0, 9, 0x0344, 9, &leaf3_gate_lock }, /* 46-50 */
+	{ "GNSS_SYS_M0", 0x04D0, 10, 0x0344, 10, &leaf3_gate_lock },
+	{ "CANBUS1", 0x04D0, 12, 0x0344, 11, &leaf3_gate_lock },
+	{ "CCSEC", 0x04D0, 15, 0x0344, 12, &leaf3_gate_lock },
+	{ "CCPUB", 0x04D0, 16, 0x0344, 13, &leaf3_gate_lock },
+	{ "DAPA_GNSSM", 0x04D0, 13, 0x0344, 14, &leaf3_gate_lock }, /* 51-55 */
+	{ "THGNSSM", 0x04D0, 14, 0x0344, 15, &leaf3_gate_lock },
+	{ "VDEC", 0x04E8, 0, 0x0350, 0, &leaf4_gate_lock },
+	{ "JPENC", 0x04E8, 1, 0x0350, 1, &leaf4_gate_lock },
+	{ "G2D", 0x04E8, 2, 0x0350, 2, &leaf4_gate_lock },
+	{ "I2C0", 0x04E8, 3, 0x0350, 3, &leaf4_gate_lock }, /* 56-60 */
+	{ "I2C1", 0x04E8, 4, 0x0350, 4, &leaf4_gate_lock },
+	{ "GPIO0", 0x04E8, 5, 0x0350, 5, &leaf4_gate_lock },
+	{ "NAND", 0x04E8, 6, 0x0350, 6, &leaf4_gate_lock },
+	{ "SDIO01", 0x04E8, 7, 0x0350, 7, &leaf4_gate_lock },
+	{ "SYS2PCI2", 0x04E8, 8, 0x0350, 8, &leaf4_gate_lock }, /* 61-65 */
+	{ "USB0", 0x04E8, 11, 0x0350, 9, &leaf4_gate_lock },
+	{ "USB1", 0x04E8, 12, 0x0350, 10, &leaf4_gate_lock },
+	{ "THMEDIAM", 0x04E8, 15, 0x0350, 11, &leaf4_gate_lock },
+	{ "MEMC_DDRPHY", 0x0500, 0, 0x035C, 0, &leaf5_gate_lock },
+	{ "MEMC_UPCTL", 0x0500, 0, 0x035C, 1, &leaf5_gate_lock }, /* 66-70 */
+	{ "DAPA_MEM", 0x0500, 1, 0x035C, 2, &leaf5_gate_lock },
+	{ "MEMC_MEMDIV", 0x0500, 0, 0x035C, 3, &leaf5_gate_lock },
+	{ "THDDRM", 0x0500, 3, 0x035C, 4, &leaf5_gate_lock },
+	{ "CORESIGHT", 0x0518, 3, 0x0368, 13, &leaf6_gate_lock },
+	{ "THCPUM", 0x0518, 4, 0x0368, 17, &leaf6_gate_lock }, /* 71-75 */
+	{ "GRAPHIC", 0x0530, 0, 0x0374, 0, &leaf7_gate_lock },
+	{ "VSS_SDR", 0x0530, 1, 0x0374, 1, &leaf7_gate_lock },
+	{ "THGPUM", 0x0530, 2, 0x0374, 2, &leaf7_gate_lock },
+	{ "DMAC4", 0x0548, 2, 0x0380, 1, &leaf8_gate_lock },
+	{ "UART6", 0x0548, 3, 0x0380, 2, &leaf8_gate_lock }, /* 76- */
+	{ "USP3", 0x0548, 4, 0x0380, 3, &leaf8_gate_lock },
+	{ "THBTM", 0x0548, 5, 0x0380, 5, &leaf8_gate_lock },
+	{ "A7CA", 0x0548, 1, 0x0380, 0, &leaf8_gate_lock },
+	{ "A7CA_APB", 0x0548, 5, 0x0380, 4, &leaf8_gate_lock },
+};
+
+static int atlas7_reset_module(struct reset_controller_dev *rcdev,
+					unsigned long reset_idx)
+{
+	struct atlas7_reset_desc *reset = &atlas7_reset_unit[reset_idx];
+	unsigned long flags;
+
+	/*
+	 * HW suggest unit reset sequence:
+	 * assert sw reset (0)
+	 * setting sw clk_en to if the clock was disabled before reset
+	 * delay 16 clocks
+	 * disable clock (sw clk_en = 0)
+	 * de-assert reset (1)
+	 * after this sequence, restore clock or not is decided by SW
+	 */
+
+	spin_lock_irqsave(reset->lock, flags);
+	/* clock enable or not */
+	if (clkc_readl(reset->clk_ofs + 8) & (1 << reset->clk_bit)) {
+		clkc_writel(1 << reset->rst_bit, reset->rst_ofs + 4);
+		udelay(2);
+		clkc_writel(1 << reset->clk_bit, reset->clk_ofs + 4);
+		clkc_writel(1 << reset->rst_bit, reset->rst_ofs);
+		/* restore clock enable */
+		clkc_writel(1 << reset->clk_bit, reset->clk_ofs);
+	} else {
+		clkc_writel(1 << reset->rst_bit, reset->rst_ofs + 4);
+		clkc_writel(1 << reset->clk_bit, reset->clk_ofs);
+		udelay(2);
+		clkc_writel(1 << reset->clk_bit, reset->clk_ofs + 4);
+		clkc_writel(1 << reset->rst_bit, reset->rst_ofs);
+	}
+	spin_unlock_irqrestore(reset->lock, flags);
+
+	return 0;
+}
+
+static struct reset_control_ops atlas7_rst_ops = {
+	.reset = atlas7_reset_module,
+};
+
+static struct reset_controller_dev atlas7_rst_ctlr = {
+	.ops = &atlas7_rst_ops,
+	.owner = THIS_MODULE,
+	.of_reset_n_cells = 1,
+};
+
+static void __init atlas7_clk_init(struct device_node *np)
+{
+	struct clk *clk;
+	struct atlas7_div_init_data *div;
+	struct atlas7_mux_init_data *mux;
+	struct atlas7_unit_init_data *unit;
+	int i;
+	int ret;
+
+	sirfsoc_clk_vbase = of_iomap(np, 0);
+	if (!sirfsoc_clk_vbase)
+		panic("unable to map clkc registers\n");
+
+	of_node_put(np);
+
+	clk = clk_register(NULL, &clk_cpupll.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_mempll.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_sys0pll.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_sys1pll.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_sys2pll.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_sys3pll.hw);
+	BUG_ON(!clk);
+
+	clk = clk_register_divider_table(NULL, "cpupll_div1", "cpupll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, 0, 3, 0,
+			 pll_div_table, &cpupll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "cpupll_div2", "cpupll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, 4, 3, 0,
+			 pll_div_table, &cpupll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "cpupll_div3", "cpupll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, 8, 3, 0,
+			 pll_div_table, &cpupll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register_divider_table(NULL, "mempll_div1", "mempll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, 0, 3, 0,
+			 pll_div_table, &mempll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "mempll_div2", "mempll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, 4, 3, 0,
+			 pll_div_table, &mempll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "mempll_div3", "mempll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, 8, 3, 0,
+			 pll_div_table, &mempll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register_divider_table(NULL, "sys0pll_div1", "sys0pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, 0, 3, 0,
+			 pll_div_table, &sys0pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys0pll_div2", "sys0pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, 4, 3, 0,
+			 pll_div_table, &sys0pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys0pll_div3", "sys0pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, 8, 3, 0,
+			 pll_div_table, &sys0pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_fixed_factor(NULL, "sys0pll_fixdiv", "sys0pll_vco",
+					CLK_SET_RATE_PARENT, 1, 2);
+
+	clk = clk_register_divider_table(NULL, "sys1pll_div1", "sys1pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, 0, 3, 0,
+			 pll_div_table, &sys1pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys1pll_div2", "sys1pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, 4, 3, 0,
+			 pll_div_table, &sys1pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys1pll_div3", "sys1pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, 8, 3, 0,
+			 pll_div_table, &sys1pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_fixed_factor(NULL, "sys1pll_fixdiv", "sys1pll_vco",
+					CLK_SET_RATE_PARENT, 1, 2);
+
+	clk = clk_register_divider_table(NULL, "sys2pll_div1", "sys2pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, 0, 3, 0,
+			 pll_div_table, &sys2pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys2pll_div2", "sys2pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, 4, 3, 0,
+			 pll_div_table, &sys2pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys2pll_div3", "sys2pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, 8, 3, 0,
+			 pll_div_table, &sys2pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_fixed_factor(NULL, "sys2pll_fixdiv", "sys2pll_vco",
+					CLK_SET_RATE_PARENT, 1, 2);
+
+	clk = clk_register_divider_table(NULL, "sys3pll_div1", "sys3pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, 0, 3, 0,
+			 pll_div_table, &sys3pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys3pll_div2", "sys3pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, 4, 3, 0,
+			 pll_div_table, &sys3pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_divider_table(NULL, "sys3pll_div3", "sys3pll_vco", 0,
+			 sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, 8, 3, 0,
+			 pll_div_table, &sys3pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_fixed_factor(NULL, "sys3pll_fixdiv", "sys3pll_vco",
+					CLK_SET_RATE_PARENT, 1, 2);
+
+	BUG_ON(!clk);
+	clk = clk_register_fixed_factor(NULL, "xinw_fixdiv_btslow", "xinw",
+					CLK_SET_RATE_PARENT, 1, 4);
+
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "cpupll_clk1", "cpupll_div1",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1,
+				12, 0, &cpupll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "cpupll_clk2", "cpupll_div2",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1,
+				13, 0, &cpupll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "cpupll_clk3", "cpupll_div3",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1,
+				14, 0, &cpupll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register_gate(NULL, "mempll_clk1", "mempll_div1",
+		CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+		sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1,
+		12, 0, &mempll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "mempll_clk2", "mempll_div2",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1,
+				13, 0, &mempll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "mempll_clk3", "mempll_div3",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1,
+				14, 0, &mempll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register_gate(NULL, "sys0pll_clk1", "sys0pll_div1",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1,
+				12, 0, &sys0pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys0pll_clk2", "sys0pll_div2",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1,
+				13, 0, &sys0pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys0pll_clk3", "sys0pll_div3",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1,
+				14, 0, &sys0pll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register_gate(NULL, "sys1pll_clk1", "sys1pll_div1",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1,
+				12, 0, &sys1pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys1pll_clk2", "sys1pll_div2",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1,
+				13, 0, &sys1pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys1pll_clk3", "sys1pll_div3",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1,
+				14, 0, &sys1pll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register_gate(NULL, "sys2pll_clk1", "sys2pll_div1",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1,
+				12, 0, &sys2pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys2pll_clk2", "sys2pll_div2",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1,
+				13, 0, &sys2pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys2pll_clk3", "sys2pll_div3",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1,
+				14, 0, &sys2pll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register_gate(NULL, "sys3pll_clk1", "sys3pll_div1",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1,
+				12, 0, &sys3pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys3pll_clk2", "sys3pll_div2",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1,
+				13, 0, &sys3pll_ctrl1_lock);
+	BUG_ON(!clk);
+	clk = clk_register_gate(NULL, "sys3pll_clk3", "sys3pll_div3",
+		CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1,
+				14, 0, &sys3pll_ctrl1_lock);
+	BUG_ON(!clk);
+
+	clk = clk_register(NULL, &clk_audio_dto.hw);
+	BUG_ON(!clk);
+
+	clk = clk_register(NULL, &clk_disp0_dto.hw);
+	BUG_ON(!clk);
+
+	clk = clk_register(NULL, &clk_disp1_dto.hw);
+	BUG_ON(!clk);
+
+	for (i = 0; i < ARRAY_SIZE(divider_list); i++) {
+		div = &divider_list[i];
+		clk = clk_register_divider(NULL, div->div_name,
+			div->parent_name, div->divider_flags, sirfsoc_clk_vbase + div->div_offset,
+			div->shift, div->width, 0, div->lock);
+		BUG_ON(!clk);
+		clk = clk_register_gate(NULL, div->gate_name, div->div_name,
+			div->gate_flags, sirfsoc_clk_vbase + div->gate_offset,
+				div->gate_bit, 0, div->lock);
+		BUG_ON(!clk);
+	}
+	/* ignore selector status register check */
+	for (i = 0; i < ARRAY_SIZE(mux_list); i++) {
+		mux = &mux_list[i];
+		clk = clk_register_mux(NULL, mux->mux_name, mux->parent_names,
+			       mux->parent_num, mux->flags,
+			       sirfsoc_clk_vbase + mux->mux_offset,
+			       mux->shift, mux->width,
+			       mux->mux_flags, NULL);
+		BUG_ON(!clk);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(unit_list); i++) {
+		unit = &unit_list[i];
+		atlas7_clks[i] = atlas7_unit_clk_register(NULL, unit->unit_name, unit->parent_name,
+				unit->flags, unit->regofs, unit->bit, unit->lock);
+		BUG_ON(!atlas7_clks[i]);
+	}
+
+	clk_data.clks = atlas7_clks;
+	clk_data.clk_num = ARRAY_SIZE(unit_list);
+
+	ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+	BUG_ON(ret);
+
+	atlas7_rst_ctlr.of_node = np;
+	atlas7_rst_ctlr.nr_resets = ARRAY_SIZE(atlas7_reset_unit);
+	reset_controller_register(&atlas7_rst_ctlr);
+}
+CLK_OF_DECLARE(atlas7_clk, "sirf,atlas7-car", atlas7_clk_init);

From 9c684e290d1741e068cc226418a26a39663db010 Mon Sep 17 00:00:00 2001
From: Guo Zeng <Guo.Zeng@csr.com>
Date: Wed, 20 May 2015 08:50:34 +0000
Subject: [PATCH 070/135] ARM: dts: atlas7: add fixed frequency clocks in car
 node

This patch adds the fixed clocks of external crystal oscillators.

Signed-off-by: Guo Zeng <Guo.Zeng@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
[sboyd@codeaurora.org: Remove size-cells/address-cells]
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 arch/arm/boot/dts/atlas7.dtsi | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/arch/arm/boot/dts/atlas7.dtsi b/arch/arm/boot/dts/atlas7.dtsi
index a753178abc85..5dfd3a44bf82 100644
--- a/arch/arm/boot/dts/atlas7.dtsi
+++ b/arch/arm/boot/dts/atlas7.dtsi
@@ -38,6 +38,21 @@
 		};
 	};
 
+	clocks {
+		xinw {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+			clock-output-names = "xinw";
+		};
+		xin {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <26000000>;
+			clock-output-names = "xin";
+		};
+	};
+
 	noc {
 		compatible = "simple-bus";
 		#address-cells = <1>;

From a59a516398750dc3477a81df34e655b596e352b3 Mon Sep 17 00:00:00 2001
From: Shailendra Verma <shailendra.capricorn@gmail.com>
Date: Thu, 21 May 2015 00:06:48 +0530
Subject: [PATCH 071/135] clk: Fix typo in clk_register() comment

Signed-off-by: Shailendra Verma <shailendra.capricorn@gmail.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index c44623fe9c48..a522dbbc01b9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2442,7 +2442,7 @@ void __clk_free_clk(struct clk *clk)
  *
  * clk_register is the primary interface for populating the clock tree with new
  * clock nodes.  It returns a pointer to the newly allocated struct clk which
- * cannot be dereferenced by driver code but may be used in conjuction with the
+ * cannot be dereferenced by driver code but may be used in conjunction with the
  * rest of the clock API.  In the event of an error clk_register will return an
  * error code; drivers must test for an error code after calling clk_register.
  */

From 8cdea5022dade063a10ffb0f768a18bfabab40e3 Mon Sep 17 00:00:00 2001
From: Axel Lin <axel.lin@ingics.com>
Date: Thu, 21 May 2015 22:26:13 +0800
Subject: [PATCH 072/135] clk: cdce706: Add missing of_clk_del_provider call in
 cdce706_remove

Remove a previously registered clock provider when unload the module.

Signed-off-by: Axel Lin <axel.lin@ingics.com>
Acked-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-cdce706.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/clk-cdce706.c b/drivers/clk/clk-cdce706.c
index 8a2dfd0012f3..f01164fada5d 100644
--- a/drivers/clk/clk-cdce706.c
+++ b/drivers/clk/clk-cdce706.c
@@ -666,6 +666,7 @@ static int cdce706_probe(struct i2c_client *client,
 
 static int cdce706_remove(struct i2c_client *client)
 {
+	of_clk_del_provider(client->dev.of_node);
 	return 0;
 }
 

From c306317a0e285670d8cceab067d5aceff4593ec8 Mon Sep 17 00:00:00 2001
From: Shailendra Verma <shailendra.capricorn@gmail.com>
Date: Thu, 21 May 2015 23:26:03 +0530
Subject: [PATCH 073/135] clk: samsung: Fix typo in panic log

Signed-off-by: Shailendra Verma <shailendra.capricorn@gmail.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/samsung/clk.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index 9e1f88c04fd4..76491629d1e5 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -389,7 +389,7 @@ struct samsung_clk_provider * __init samsung_cmu_register_one(
 
 	ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids);
 	if (!ctx) {
-		panic("%s: unable to alllocate ctx\n", __func__);
+		panic("%s: unable to allocate ctx\n", __func__);
 		return ctx;
 	}
 

From 004cbb475fb0164665d66c68e509a4af64f7f5f1 Mon Sep 17 00:00:00 2001
From: Shailendra Verma <shailendra.capricorn@gmail.com>
Date: Thu, 21 May 2015 23:32:56 +0530
Subject: [PATCH 074/135] clk: clk-conf: Fix typo in comment

Signed-off-by: Shailendra Verma <shailendra.capricorn@gmail.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-conf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
index 35a396bc9672..43a218f35b19 100644
--- a/drivers/clk/clk-conf.c
+++ b/drivers/clk/clk-conf.c
@@ -125,7 +125,7 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
  * and sets any specified clock parents and rates. The @clk_supplier argument
  * should be set to true if @node may be also a clock supplier of any clock
  * listed in its 'assigned-clocks' or 'assigned-clock-parents' properties.
- * If @clk_supplier is false the function exits returnning 0 as soon as it
+ * If @clk_supplier is false the function exits returning 0 as soon as it
  * determines the @node is also a supplier of any of the clocks.
  */
 int of_clk_set_defaults(struct device_node *node, bool clk_supplier)

From 5611a5ba8e5435740df99235b262b553f687b13b Mon Sep 17 00:00:00 2001
From: Dinh Nguyen <dinguyen@opensource.altera.com>
Date: Tue, 19 May 2015 22:22:41 -0500
Subject: [PATCH 075/135] clk: socfpga: update clk.h so for Arria10 platform to
 use

There are 5 possible parent clocks for the SoCFPGA Arria10. Move the define
SYSMGR_SDMMC_CTRL_SET and streq() to clk.h so that the Arria clock driver
can use.

Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/socfpga/clk-gate.c | 4 ----
 drivers/clk/socfpga/clk.h      | 6 +++++-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c
index 0d5dc84372dc..0add360525a0 100644
--- a/drivers/clk/socfpga/clk-gate.c
+++ b/drivers/clk/socfpga/clk-gate.c
@@ -32,14 +32,10 @@
 #define SOCFPGA_MMC_CLK			"sdmmc_clk"
 #define SOCFPGA_GPIO_DB_CLK_OFFSET	0xA8
 
-#define streq(a, b) (strcmp((a), (b)) == 0)
-
 #define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
 
 /* SDMMC Group for System Manager defines */
 #define SYSMGR_SDMMCGRP_CTRL_OFFSET    0x108
-#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \
-	((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0))
 
 static u8 socfpga_clk_get_parent(struct clk_hw *hwclk)
 {
diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
index d291f60c46e1..b09a5d50547e 100644
--- a/drivers/clk/socfpga/clk.h
+++ b/drivers/clk/socfpga/clk.h
@@ -26,9 +26,13 @@
 #define CLKMGR_L4SRC		0x70
 #define CLKMGR_PERPLL_SRC	0xAC
 
-#define SOCFPGA_MAX_PARENTS		3
+#define SOCFPGA_MAX_PARENTS		5
 #define div_mask(width) ((1 << (width)) - 1)
 
+#define streq(a, b) (strcmp((a), (b)) == 0)
+#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel) \
+	((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0))
+
 extern void __iomem *clk_mgr_base_addr;
 
 void __init socfpga_pll_init(struct device_node *node);

From 5343325ff3dd299f459fa9dacbd95dca5c9bf215 Mon Sep 17 00:00:00 2001
From: Dinh Nguyen <dinguyen@opensource.altera.com>
Date: Tue, 19 May 2015 22:22:42 -0500
Subject: [PATCH 076/135] clk: socfpga: add a clock driver for the Arria 10
 platform

The clocks on the Arria 10 platform is a bit different than the
Cyclone/Arria 5 platform that it should just have it's own
driver.

Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/socfpga/Makefile         |   1 +
 drivers/clk/socfpga/clk-gate-a10.c   | 190 +++++++++++++++++++++++++++
 drivers/clk/socfpga/clk-periph-a10.c | 138 +++++++++++++++++++
 drivers/clk/socfpga/clk-pll-a10.c    | 129 ++++++++++++++++++
 drivers/clk/socfpga/clk.c            |   7 +-
 drivers/clk/socfpga/clk.h            |   5 +
 6 files changed, 469 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/socfpga/clk-gate-a10.c
 create mode 100644 drivers/clk/socfpga/clk-periph-a10.c
 create mode 100644 drivers/clk/socfpga/clk-pll-a10.c

diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
index 7e2d15a0c7b8..d8bb239753a4 100644
--- a/drivers/clk/socfpga/Makefile
+++ b/drivers/clk/socfpga/Makefile
@@ -2,3 +2,4 @@ obj-y += clk.o
 obj-y += clk-gate.o
 obj-y += clk-pll.o
 obj-y += clk-periph.o
+obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o
diff --git a/drivers/clk/socfpga/clk-gate-a10.c b/drivers/clk/socfpga/clk-gate-a10.c
new file mode 100644
index 000000000000..be3e998b85d0
--- /dev/null
+++ b/drivers/clk/socfpga/clk-gate-a10.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2015 Altera Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+#include "clk.h"
+
+#define streq(a, b) (strcmp((a), (b)) == 0)
+
+#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
+
+/* SDMMC Group for System Manager defines */
+#define SYSMGR_SDMMCGRP_CTRL_OFFSET	0x28
+
+static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
+	unsigned long parent_rate)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	u32 div = 1, val;
+
+	if (socfpgaclk->fixed_div)
+		div = socfpgaclk->fixed_div;
+	else if (socfpgaclk->div_reg) {
+		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+		val &= div_mask(socfpgaclk->width);
+			div = (1 << val);
+	}
+
+	return parent_rate / div;
+}
+
+static int socfpga_clk_prepare(struct clk_hw *hwclk)
+{
+	struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
+	int i;
+	u32 hs_timing;
+	u32 clk_phase[2];
+
+	if (socfpgaclk->clk_phase[0] || socfpgaclk->clk_phase[1]) {
+		for (i = 0; i < ARRAY_SIZE(clk_phase); i++) {
+			switch (socfpgaclk->clk_phase[i]) {
+			case 0:
+				clk_phase[i] = 0;
+				break;
+			case 45:
+				clk_phase[i] = 1;
+				break;
+			case 90:
+				clk_phase[i] = 2;
+				break;
+			case 135:
+				clk_phase[i] = 3;
+				break;
+			case 180:
+				clk_phase[i] = 4;
+				break;
+			case 225:
+				clk_phase[i] = 5;
+				break;
+			case 270:
+				clk_phase[i] = 6;
+				break;
+			case 315:
+				clk_phase[i] = 7;
+				break;
+			default:
+				clk_phase[i] = 0;
+				break;
+			}
+		}
+
+		hs_timing = SYSMGR_SDMMC_CTRL_SET(clk_phase[0], clk_phase[1]);
+		if (!IS_ERR(socfpgaclk->sys_mgr_base_addr))
+			regmap_write(socfpgaclk->sys_mgr_base_addr,
+				     SYSMGR_SDMMCGRP_CTRL_OFFSET, hs_timing);
+		else
+			pr_err("%s: cannot set clk_phase because sys_mgr_base_addr is not available!\n",
+					__func__);
+	}
+	return 0;
+}
+
+static struct clk_ops gateclk_ops = {
+	.prepare = socfpga_clk_prepare,
+	.recalc_rate = socfpga_gate_clk_recalc_rate,
+};
+
+static void __init __socfpga_gate_init(struct device_node *node,
+	const struct clk_ops *ops)
+{
+	u32 clk_gate[2];
+	u32 div_reg[3];
+	u32 clk_phase[2];
+	u32 fixed_div;
+	struct clk *clk;
+	struct socfpga_gate_clk *socfpga_clk;
+	const char *clk_name = node->name;
+	const char *parent_name[SOCFPGA_MAX_PARENTS];
+	struct clk_init_data init;
+	int rc;
+	int i = 0;
+
+	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
+	if (WARN_ON(!socfpga_clk))
+		return;
+
+	rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2);
+	if (rc)
+		clk_gate[0] = 0;
+
+	if (clk_gate[0]) {
+		socfpga_clk->hw.reg = clk_mgr_a10_base_addr + clk_gate[0];
+		socfpga_clk->hw.bit_idx = clk_gate[1];
+
+		gateclk_ops.enable = clk_gate_ops.enable;
+		gateclk_ops.disable = clk_gate_ops.disable;
+	}
+
+	rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
+	if (rc)
+		socfpga_clk->fixed_div = 0;
+	else
+		socfpga_clk->fixed_div = fixed_div;
+
+	rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
+	if (!rc) {
+		socfpga_clk->div_reg = clk_mgr_a10_base_addr + div_reg[0];
+		socfpga_clk->shift = div_reg[1];
+		socfpga_clk->width = div_reg[2];
+	} else {
+		socfpga_clk->div_reg = NULL;
+	}
+
+	rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2);
+	if (!rc) {
+		socfpga_clk->clk_phase[0] = clk_phase[0];
+		socfpga_clk->clk_phase[1] = clk_phase[1];
+
+		socfpga_clk->sys_mgr_base_addr =
+			syscon_regmap_lookup_by_compatible("altr,sys-mgr");
+		if (IS_ERR(socfpga_clk->sys_mgr_base_addr)) {
+			pr_err("%s: failed to find altr,sys-mgr regmap!\n",
+					__func__);
+			return;
+		}
+	}
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	init.name = clk_name;
+	init.ops = ops;
+	init.flags = 0;
+	while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] =
+			of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+
+	init.parent_names = parent_name;
+	init.num_parents = i;
+	socfpga_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &socfpga_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(socfpga_clk);
+		return;
+	}
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	if (WARN_ON(rc))
+		return;
+}
+
+void __init socfpga_a10_gate_init(struct device_node *node)
+{
+	__socfpga_gate_init(node, &gateclk_ops);
+}
diff --git a/drivers/clk/socfpga/clk-periph-a10.c b/drivers/clk/socfpga/clk-periph-a10.c
new file mode 100644
index 000000000000..9d0181b5a6a4
--- /dev/null
+++ b/drivers/clk/socfpga/clk-periph-a10.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2015 Altera Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#include "clk.h"
+
+#define CLK_MGR_FREE_SHIFT		16
+#define CLK_MGR_FREE_MASK		0x7
+
+#define SOCFPGA_MPU_FREE_CLK		"mpu_free_clk"
+#define SOCFPGA_NOC_FREE_CLK		"noc_free_clk"
+#define SOCFPGA_SDMMC_FREE_CLK		"sdmmc_free_clk"
+#define to_socfpga_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
+
+static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
+					     unsigned long parent_rate)
+{
+	struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk);
+	u32 div;
+
+	if (socfpgaclk->fixed_div) {
+		div = socfpgaclk->fixed_div;
+	} else if (socfpgaclk->div_reg) {
+		div = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
+		div &= div_mask(socfpgaclk->width);
+		div += 1;
+	} else {
+		div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
+	}
+
+	return parent_rate / div;
+}
+
+static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk);
+	u32 clk_src;
+
+	clk_src = readl(socfpgaclk->hw.reg);
+	if (streq(hwclk->init->name, SOCFPGA_MPU_FREE_CLK) ||
+	    streq(hwclk->init->name, SOCFPGA_NOC_FREE_CLK) ||
+	    streq(hwclk->init->name, SOCFPGA_SDMMC_FREE_CLK))
+		return (clk_src >> CLK_MGR_FREE_SHIFT) &
+			CLK_MGR_FREE_MASK;
+	else
+		return 0;
+}
+
+static const struct clk_ops periclk_ops = {
+	.recalc_rate = clk_periclk_recalc_rate,
+	.get_parent = clk_periclk_get_parent,
+};
+
+static __init void __socfpga_periph_init(struct device_node *node,
+	const struct clk_ops *ops)
+{
+	u32 reg;
+	struct clk *clk;
+	struct socfpga_periph_clk *periph_clk;
+	const char *clk_name = node->name;
+	const char *parent_name;
+	struct clk_init_data init;
+	int rc;
+	u32 fixed_div;
+	u32 div_reg[3];
+
+	of_property_read_u32(node, "reg", &reg);
+
+	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
+	if (WARN_ON(!periph_clk))
+		return;
+
+	periph_clk->hw.reg = clk_mgr_a10_base_addr + reg;
+
+	rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
+	if (!rc) {
+		periph_clk->div_reg = clk_mgr_a10_base_addr + div_reg[0];
+		periph_clk->shift = div_reg[1];
+		periph_clk->width = div_reg[2];
+	} else {
+		periph_clk->div_reg = NULL;
+	}
+
+	rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
+	if (rc)
+		periph_clk->fixed_div = 0;
+	else
+		periph_clk->fixed_div = fixed_div;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	init.name = clk_name;
+	init.ops = ops;
+	init.flags = 0;
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	init.num_parents = 1;
+	init.parent_names = &parent_name;
+
+	periph_clk->hw.hw.init = &init;
+
+	clk = clk_register(NULL, &periph_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(periph_clk);
+		return;
+	}
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	if (rc < 0) {
+		pr_err("Could not register clock provider for node:%s\n",
+		       clk_name);
+		goto err_clk;
+	}
+
+	return;
+
+err_clk:
+	clk_unregister(clk);
+}
+
+void __init socfpga_a10_periph_init(struct device_node *node)
+{
+	__socfpga_periph_init(node, &periclk_ops);
+}
diff --git a/drivers/clk/socfpga/clk-pll-a10.c b/drivers/clk/socfpga/clk-pll-a10.c
new file mode 100644
index 000000000000..1178b11babca
--- /dev/null
+++ b/drivers/clk/socfpga/clk-pll-a10.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2015 Altera Corporation. All rights reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk.h"
+
+/* Clock Manager offsets */
+#define CLK_MGR_PLL_CLK_SRC_SHIFT	8
+#define CLK_MGR_PLL_CLK_SRC_MASK	0x3
+
+/* Clock bypass bits */
+#define SOCFPGA_PLL_BG_PWRDWN		0
+#define SOCFPGA_PLL_PWR_DOWN		1
+#define SOCFPGA_PLL_EXT_ENA		2
+#define SOCFPGA_PLL_DIVF_MASK		0x00001FFF
+#define SOCFPGA_PLL_DIVF_SHIFT	0
+#define SOCFPGA_PLL_DIVQ_MASK		0x003F0000
+#define SOCFPGA_PLL_DIVQ_SHIFT	16
+#define SOCFGPA_MAX_PARENTS	5
+
+#define SOCFPGA_MAIN_PLL_CLK		"main_pll"
+#define SOCFPGA_PERIP_PLL_CLK		"periph_pll"
+
+#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
+
+void __iomem *clk_mgr_a10_base_addr;
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
+					 unsigned long parent_rate)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	unsigned long divf, divq, reg;
+	unsigned long long vco_freq;
+
+	/* read VCO1 reg for numerator and denominator */
+	reg = readl(socfpgaclk->hw.reg + 0x4);
+	divf = (reg & SOCFPGA_PLL_DIVF_MASK) >> SOCFPGA_PLL_DIVF_SHIFT;
+	divq = (reg & SOCFPGA_PLL_DIVQ_MASK) >> SOCFPGA_PLL_DIVQ_SHIFT;
+	vco_freq = (unsigned long long)parent_rate * (divf + 1);
+	do_div(vco_freq, (1 + divq));
+	return (unsigned long)vco_freq;
+}
+
+static u8 clk_pll_get_parent(struct clk_hw *hwclk)
+{
+	struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
+	u32 pll_src;
+
+	pll_src = readl(socfpgaclk->hw.reg);
+
+	return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
+		CLK_MGR_PLL_CLK_SRC_MASK;
+}
+
+static struct clk_ops clk_pll_ops = {
+	.recalc_rate = clk_pll_recalc_rate,
+	.get_parent = clk_pll_get_parent,
+};
+
+static struct __init clk * __socfpga_pll_init(struct device_node *node,
+	const struct clk_ops *ops)
+{
+	u32 reg;
+	struct clk *clk;
+	struct socfpga_pll *pll_clk;
+	const char *clk_name = node->name;
+	const char *parent_name[SOCFGPA_MAX_PARENTS];
+	struct clk_init_data init;
+	struct device_node *clkmgr_np;
+	int rc;
+	int i = 0;
+
+	of_property_read_u32(node, "reg", &reg);
+
+	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
+	if (WARN_ON(!pll_clk))
+		return NULL;
+
+	clkmgr_np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr");
+	clk_mgr_a10_base_addr = of_iomap(clkmgr_np, 0);
+	BUG_ON(!clk_mgr_a10_base_addr);
+	pll_clk->hw.reg = clk_mgr_a10_base_addr + reg;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	init.name = clk_name;
+	init.ops = ops;
+	init.flags = 0;
+
+	while (i < SOCFGPA_MAX_PARENTS && (parent_name[i] =
+			of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+	init.num_parents = i;
+	init.parent_names = parent_name;
+	pll_clk->hw.hw.init = &init;
+
+	pll_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA;
+	clk_pll_ops.enable = clk_gate_ops.enable;
+	clk_pll_ops.disable = clk_gate_ops.disable;
+
+	clk = clk_register(NULL, &pll_clk->hw.hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(pll_clk);
+		return NULL;
+	}
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	return clk;
+}
+
+void __init socfpga_a10_pll_init(struct device_node *node)
+{
+	__socfpga_pll_init(node, &clk_pll_ops);
+}
diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c
index 43db947e5f0e..7564d2e35f32 100644
--- a/drivers/clk/socfpga/clk.c
+++ b/drivers/clk/socfpga/clk.c
@@ -24,4 +24,9 @@
 CLK_OF_DECLARE(socfpga_pll_clk, "altr,socfpga-pll-clock", socfpga_pll_init);
 CLK_OF_DECLARE(socfpga_perip_clk, "altr,socfpga-perip-clk", socfpga_periph_init);
 CLK_OF_DECLARE(socfpga_gate_clk, "altr,socfpga-gate-clk", socfpga_gate_init);
-
+CLK_OF_DECLARE(socfpga_a10_pll_clk, "altr,socfpga-a10-pll-clock",
+	       socfpga_a10_pll_init);
+CLK_OF_DECLARE(socfpga_a10_perip_clk, "altr,socfpga-a10-perip-clk",
+	       socfpga_a10_periph_init);
+CLK_OF_DECLARE(socfpga_a10_gate_clk, "altr,socfpga-a10-gate-clk",
+	       socfpga_a10_gate_init);
diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
index b09a5d50547e..603973ab7e29 100644
--- a/drivers/clk/socfpga/clk.h
+++ b/drivers/clk/socfpga/clk.h
@@ -34,10 +34,14 @@
 	((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0))
 
 extern void __iomem *clk_mgr_base_addr;
+extern void __iomem *clk_mgr_a10_base_addr;
 
 void __init socfpga_pll_init(struct device_node *node);
 void __init socfpga_periph_init(struct device_node *node);
 void __init socfpga_gate_init(struct device_node *node);
+void socfpga_a10_pll_init(struct device_node *node);
+void socfpga_a10_periph_init(struct device_node *node);
+void socfpga_a10_gate_init(struct device_node *node);
 
 struct socfpga_pll {
 	struct clk_gate	hw;
@@ -48,6 +52,7 @@ struct socfpga_gate_clk {
 	char *parent_name;
 	u32 fixed_div;
 	void __iomem *div_reg;
+	struct regmap *sys_mgr_base_addr;
 	u32 width;	/* only valid if div_reg != 0 */
 	u32 shift;	/* only valid if div_reg != 0 */
 	u32 clk_phase[2];

From 31a0b5373c7562d5a24f973a2afec1785d72d9c4 Mon Sep 17 00:00:00 2001
From: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
Date: Thu, 26 Feb 2015 17:42:06 +0100
Subject: [PATCH 077/135] clk: shmobile: Add r8a7778 SoC to MSTP bindings

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 .../devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt        | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
index 0a80fa70ca26..e163092348bf 100644
--- a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
@@ -13,6 +13,7 @@ Required Properties:
     - "renesas,r7s72100-mstp-clocks" for R7S72100 (RZ) MSTP gate clocks
     - "renesas,r8a73a4-mstp-clocks" for R8A73A4 (R-Mobile APE6) MSTP gate clocks
     - "renesas,r8a7740-mstp-clocks" for R8A7740 (R-Mobile A1) MSTP gate clocks
+    - "renesas,r8a7778-mstp-clocks" for R8A7778 (R-Car M1) MSTP gate clocks
     - "renesas,r8a7779-mstp-clocks" for R8A7779 (R-Car H1) MSTP gate clocks
     - "renesas,r8a7790-mstp-clocks" for R8A7790 (R-Car H2) MSTP gate clocks
     - "renesas,r8a7791-mstp-clocks" for R8A7791 (R-Car M2) MSTP gate clocks

From b5405db9df8ea71435336bea8295cc4aa84ee3fa Mon Sep 17 00:00:00 2001
From: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
Date: Thu, 28 May 2015 17:17:00 +0200
Subject: [PATCH 078/135] clk: shmobile: Add r8a7793 SoC to MSTP bindings

Also replaces "R-Car M2" with "R-Car M2-W" to avoid confusion.

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
Cc: Michael Turquette <mturquette@linaro.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 .../devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt      | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
index e163092348bf..c95f7d2db6bd 100644
--- a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
@@ -16,7 +16,8 @@ Required Properties:
     - "renesas,r8a7778-mstp-clocks" for R8A7778 (R-Car M1) MSTP gate clocks
     - "renesas,r8a7779-mstp-clocks" for R8A7779 (R-Car H1) MSTP gate clocks
     - "renesas,r8a7790-mstp-clocks" for R8A7790 (R-Car H2) MSTP gate clocks
-    - "renesas,r8a7791-mstp-clocks" for R8A7791 (R-Car M2) MSTP gate clocks
+    - "renesas,r8a7791-mstp-clocks" for R8A7791 (R-Car M2-W) MSTP gate clocks
+    - "renesas,r8a7793-mstp-clocks" for R8A7793 (R-Car M2-N) MSTP gate clocks
     - "renesas,r8a7794-mstp-clocks" for R8A7794 (R-Car E2) MSTP gate clocks
     - "renesas,sh73a0-mstp-clocks" for SH73A0 (SH-MobileAG5) MSTP gate clocks
     - "renesas,cpg-mstp-clock" for generic MSTP gate clocks

From 0e0d8b7050372e5b55f5067be8a15bb7577c9b00 Mon Sep 17 00:00:00 2001
From: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
Date: Thu, 28 May 2015 17:17:01 +0200
Subject: [PATCH 079/135] clk: shmobile: r8a7793: Document DIV6 clock bindings

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
Cc: devicetree@vger.kernel.org
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 .../devicetree/bindings/clock/renesas,cpg-div6-clocks.txt      | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
index 054f65f9319c..b0a3a1147d62 100644
--- a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
@@ -10,7 +10,8 @@ Required Properties:
     - "renesas,r8a73a4-div6-clock" for R8A73A4 (R-Mobile APE6) DIV6 clocks
     - "renesas,r8a7740-div6-clock" for R8A7740 (R-Mobile A1) DIV6 clocks
     - "renesas,r8a7790-div6-clock" for R8A7790 (R-Car H2) DIV6 clocks
-    - "renesas,r8a7791-div6-clock" for R8A7791 (R-Car M2) DIV6 clocks
+    - "renesas,r8a7791-div6-clock" for R8A7791 (R-Car M2-W) DIV6 clocks
+    - "renesas,r8a7793-div6-clock" for R8A7793 (R-Car M2-N) DIV6 clocks
     - "renesas,sh73a0-div6-clock" for SH73A0 (SH-Mobile AG5) DIV6 clocks
     - "renesas,cpg-div6-clock" for generic DIV6 clocks
   - reg: Base address and length of the memory resource used by the DIV6 clock

From 0c933f3a45be471160bcf3428c1ee8f75f9cd75d Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas@glider.be>
Date: Mon, 1 Jun 2015 11:57:48 +0200
Subject: [PATCH 080/135] clk: shmobile: r8a7794: Document DIV6 clock bindings

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 .../devicetree/bindings/clock/renesas,cpg-div6-clocks.txt        | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
index b0a3a1147d62..3e40c41b0565 100644
--- a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
@@ -12,6 +12,7 @@ Required Properties:
     - "renesas,r8a7790-div6-clock" for R8A7790 (R-Car H2) DIV6 clocks
     - "renesas,r8a7791-div6-clock" for R8A7791 (R-Car M2-W) DIV6 clocks
     - "renesas,r8a7793-div6-clock" for R8A7793 (R-Car M2-N) DIV6 clocks
+    - "renesas,r8a7794-div6-clock" for R8A7794 (R-Car E2) DIV6 clocks
     - "renesas,sh73a0-div6-clock" for SH73A0 (SH-Mobile AG5) DIV6 clocks
     - "renesas,cpg-div6-clock" for generic DIV6 clocks
   - reg: Base address and length of the memory resource used by the DIV6 clock

From 370626288f1a5992951abf825c4b662ba55774c0 Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas@glider.be>
Date: Mon, 1 Jun 2015 12:00:08 +0200
Subject: [PATCH 081/135] clk: shmobile: div6: Document mandatory compatible
 fallback

The generic CPG DIV6 clock compatible value is mandatory, as the driver
uses only this value for matching.  Document that this is a fallback
that must be present.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 .../devicetree/bindings/clock/renesas,cpg-div6-clocks.txt       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
index 3e40c41b0565..5ddb68418655 100644
--- a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
@@ -14,7 +14,7 @@ Required Properties:
     - "renesas,r8a7793-div6-clock" for R8A7793 (R-Car M2-N) DIV6 clocks
     - "renesas,r8a7794-div6-clock" for R8A7794 (R-Car E2) DIV6 clocks
     - "renesas,sh73a0-div6-clock" for SH73A0 (SH-Mobile AG5) DIV6 clocks
-    - "renesas,cpg-div6-clock" for generic DIV6 clocks
+    and "renesas,cpg-div6-clock" as a fallback.
   - reg: Base address and length of the memory resource used by the DIV6 clock
   - clocks: Reference to the parent clock(s); either one, four, or eight
     clocks must be specified.  For clocks with multiple parents, invalid

From 17df1fb2e502371b63ea1b2110584e8a712d6c20 Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas@glider.be>
Date: Thu, 28 May 2015 11:28:10 +0200
Subject: [PATCH 082/135] clk: shmobile: mstp: Document mandatory compatible
 fallback

The generic MSTP gate clocks compatible value is mandatory, as the
driver uses only this value for matching.  Document that this is a
fallback that must be present.

Also fix a typo (missing plural "s") in the compatible value.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 .../devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
index c95f7d2db6bd..16ed18155160 100644
--- a/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mstp-clocks.txt
@@ -20,7 +20,7 @@ Required Properties:
     - "renesas,r8a7793-mstp-clocks" for R8A7793 (R-Car M2-N) MSTP gate clocks
     - "renesas,r8a7794-mstp-clocks" for R8A7794 (R-Car E2) MSTP gate clocks
     - "renesas,sh73a0-mstp-clocks" for SH73A0 (SH-MobileAG5) MSTP gate clocks
-    - "renesas,cpg-mstp-clock" for generic MSTP gate clocks
+    and "renesas,cpg-mstp-clocks" as a fallback.
   - reg: Base address and length of the I/O mapped registers used by the MSTP
     clocks. The first register is the clock control register and is mandatory.
     The second register is the clock status register and is optional when not

From dd734a7e773c6b9d764d2879e715aaf579a99506 Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas@glider.be>
Date: Thu, 28 May 2015 11:31:17 +0200
Subject: [PATCH 083/135] clk: shmobile: rcar-gen2: Document mandatory
 compatible fallback

The generic R-Car Gen2 CPG compatible value is mandatory, as the driver
uses only this value for matching.  Document that this is a fallback
that must be present.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 .../devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt
index b02944fba9de..56f111bd3e45 100644
--- a/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt
@@ -10,7 +10,7 @@ Required Properties:
     - "renesas,r8a7791-cpg-clocks" for the r8a7791 CPG
     - "renesas,r8a7793-cpg-clocks" for the r8a7793 CPG
     - "renesas,r8a7794-cpg-clocks" for the r8a7794 CPG
-    - "renesas,rcar-gen2-cpg-clocks" for the generic R-Car Gen2 CPG
+    and "renesas,rcar-gen2-cpg-clocks" as a fallback.
 
   - reg: Base address and length of the memory resource used by the CPG
 

From a431c1fa01ff020ecb146c04fbbea974e3eb910f Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas@glider.be>
Date: Thu, 28 May 2015 11:33:33 +0200
Subject: [PATCH 084/135] clk: shmobile: rz: Document mandatory compatible
 fallback

The generic RZ CPG compatible value is mandatory, as the driver uses
only this value for matching.  Document that this is a fallback that
must be present.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
 .../devicetree/bindings/clock/renesas,rz-cpg-clocks.txt         | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt
index 98a257492522..b0f7ddb8cdb1 100644
--- a/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt
@@ -7,7 +7,7 @@ Required Properties:
 
   - compatible: Must be one of
     - "renesas,r7s72100-cpg-clocks" for the r7s72100 CPG
-    - "renesas,rz-cpg-clocks" for the generic RZ CPG
+    and "renesas,rz-cpg-clocks" as a fallback.
   - reg: Base address and length of the memory resource used by the CPG
   - clocks: References to possible parent clocks. Order must match clock modes
     in the datasheet. For the r7s72100, this is extal, usb_x1.

From ec80749dfd859b560e8864d665d38d7a63e6a7f2 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Mon, 1 Jun 2015 20:23:27 +0200
Subject: [PATCH 085/135] clk: sunxi: Add support for the usb-clk on sun8i a23
 and a33 SoCs

The usb-clk on sun8i a23 and a33 SoCs is similar to the ones found
on sun6i-a31 SoCs but instead of a 3th phy the a23 / a33 have a hsic
interface which gets enabled by almost the same bits as used on
the a31 for the 3rd phy, but not exactly the same bits so we need
a new compatible for this.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
---
 Documentation/devicetree/bindings/clock/sunxi.txt |  1 +
 drivers/clk/sunxi/clk-usb.c                       | 11 +++++++++++
 2 files changed, 12 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 4fa11af3d378..8a47b77abfca 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -67,6 +67,7 @@ Required properties:
 	"allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20
 	"allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
 	"allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31
+	"allwinner,sun8i-a23-usb-clk" - for usb gates + resets on A23
 	"allwinner,sun9i-a80-usb-mod-clk" - for usb gates + resets on A80
 	"allwinner,sun9i-a80-usb-phy-clk" - for usb phy gates + resets on A80
 
diff --git a/drivers/clk/sunxi/clk-usb.c b/drivers/clk/sunxi/clk-usb.c
index a86ed2f8d7af..3a25f9588e67 100644
--- a/drivers/clk/sunxi/clk-usb.c
+++ b/drivers/clk/sunxi/clk-usb.c
@@ -204,6 +204,17 @@ static void __init sun6i_a31_usb_setup(struct device_node *node)
 }
 CLK_OF_DECLARE(sun6i_a31_usb, "allwinner,sun6i-a31-usb-clk", sun6i_a31_usb_setup);
 
+static const struct usb_clk_data sun8i_a23_usb_clk_data __initconst = {
+	.clk_mask = BIT(16) | BIT(11) | BIT(10) | BIT(9) | BIT(8),
+	.reset_mask = BIT(2) | BIT(1) | BIT(0),
+};
+
+static void __init sun8i_a23_usb_setup(struct device_node *node)
+{
+	sunxi_usb_clk_setup(node, &sun8i_a23_usb_clk_data, &sun4i_a10_usb_lock);
+}
+CLK_OF_DECLARE(sun8i_a23_usb, "allwinner,sun8i-a23-usb-clk", sun8i_a23_usb_setup);
+
 static const struct usb_clk_data sun9i_a80_usb_mod_data __initconst = {
 	.clk_mask = BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1),
 	.reset_mask = BIT(19) | BIT(18) | BIT(17),

From 463cfb2c9b9516a710c6320d3f6c609d33331378 Mon Sep 17 00:00:00 2001
From: Bintian Wang <bintian.wang@huawei.com>
Date: Fri, 29 May 2015 10:08:36 +0800
Subject: [PATCH 086/135] clk: hisilicon: Remove __init for marking function
 prototypes

__init markings on function prototypes are useless, so remove
them.

Suggested-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
Tested-by: Will Deacon <will.deacon@arm.com>
Tested-by: Tyler Baker <tyler.baker@linaro.org>
Tested-by: Kevin Hilman <khilman@linaro.org>
Signed-off-by: Michael Turquette <mturquette@linaro.org>
---
 drivers/clk/hisilicon/clk.h | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index 31083ffc0650..6b6f99448e01 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -95,17 +95,17 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
 				void __iomem *, u8,
 				u8, spinlock_t *);
 
-struct hisi_clock_data __init *hisi_clk_init(struct device_node *, int);
-void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
-					int, struct hisi_clock_data *);
-void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *,
-					int, struct hisi_clock_data *);
-void __init hisi_clk_register_mux(struct hisi_mux_clock *, int,
-				struct hisi_clock_data *);
-void __init hisi_clk_register_divider(struct hisi_divider_clock *,
+struct hisi_clock_data *hisi_clk_init(struct device_node *, int);
+void hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
+				int, struct hisi_clock_data *);
+void hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *,
+				int, struct hisi_clock_data *);
+void hisi_clk_register_mux(struct hisi_mux_clock *, int,
+				struct hisi_clock_data *);
+void hisi_clk_register_divider(struct hisi_divider_clock *,
+				int, struct hisi_clock_data *);
+void hisi_clk_register_gate(struct hisi_gate_clock *,
+				int, struct hisi_clock_data *);
+void hisi_clk_register_gate_sep(struct hisi_gate_clock *,
 				int, struct hisi_clock_data *);
-void __init hisi_clk_register_gate(struct hisi_gate_clock *,
-					int, struct hisi_clock_data *);
-void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *,
-					int, struct hisi_clock_data *);
 #endif	/* __HISI_CLK_H */

From 2a40a2ea109269def06f991f771c2bf2f6c0f396 Mon Sep 17 00:00:00 2001
From: Bintian Wang <bintian.wang@huawei.com>
Date: Fri, 29 May 2015 10:08:37 +0800
Subject: [PATCH 087/135] dt-bindings: Add header file of hi6220 clock driver

Add the header file "hi6220-clock.h" used by both
hi6220 clock driver and hi6220 device tree file.

Suggested-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
Tested-by: Will Deacon <will.deacon@arm.com>
Tested-by: Tyler Baker <tyler.baker@linaro.org>
Tested-by: Kevin Hilman <khilman@linaro.org>
Signed-off-by: Michael Turquette <mturquette@linaro.org>
---
 include/dt-bindings/clock/hi6220-clock.h | 173 +++++++++++++++++++++++
 1 file changed, 173 insertions(+)
 create mode 100644 include/dt-bindings/clock/hi6220-clock.h

diff --git a/include/dt-bindings/clock/hi6220-clock.h b/include/dt-bindings/clock/hi6220-clock.h
new file mode 100644
index 000000000000..70ee3833a7a0
--- /dev/null
+++ b/include/dt-bindings/clock/hi6220-clock.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_HI6220_H
+#define __DT_BINDINGS_CLOCK_HI6220_H
+
+/* clk in Hi6220 AO (always on) controller */
+#define HI6220_NONE_CLOCK	0
+
+/* fixed rate clocks */
+#define HI6220_REF32K		1
+#define HI6220_CLK_TCXO		2
+#define HI6220_MMC1_PAD		3
+#define HI6220_MMC2_PAD		4
+#define HI6220_MMC0_PAD		5
+#define HI6220_PLL_BBP		6
+#define HI6220_PLL_GPU		7
+#define HI6220_PLL1_DDR		8
+#define HI6220_PLL_SYS		9
+#define HI6220_PLL_SYS_MEDIA	10
+#define HI6220_DDR_SRC		11
+#define HI6220_PLL_MEDIA	12
+#define HI6220_PLL_DDR		13
+
+/* fixed factor clocks */
+#define HI6220_300M		14
+#define HI6220_150M		15
+#define HI6220_PICOPHY_SRC	16
+#define HI6220_MMC0_SRC_SEL	17
+#define HI6220_MMC1_SRC_SEL	18
+#define HI6220_MMC2_SRC_SEL	19
+#define HI6220_VPU_CODEC	20
+#define HI6220_MMC0_SMP		21
+#define HI6220_MMC1_SMP		22
+#define HI6220_MMC2_SMP		23
+
+/* gate clocks */
+#define HI6220_WDT0_PCLK	24
+#define HI6220_WDT1_PCLK	25
+#define HI6220_WDT2_PCLK	26
+#define HI6220_TIMER0_PCLK	27
+#define HI6220_TIMER1_PCLK	28
+#define HI6220_TIMER2_PCLK	29
+#define HI6220_TIMER3_PCLK	30
+#define HI6220_TIMER4_PCLK	31
+#define HI6220_TIMER5_PCLK	32
+#define HI6220_TIMER6_PCLK	33
+#define HI6220_TIMER7_PCLK	34
+#define HI6220_TIMER8_PCLK	35
+#define HI6220_UART0_PCLK	36
+
+#define HI6220_AO_NR_CLKS	37
+
+/* clk in Hi6220 systrl */
+/* gate clock */
+#define HI6220_MMC0_CLK		1
+#define HI6220_MMC0_CIUCLK	2
+#define HI6220_MMC1_CLK		3
+#define HI6220_MMC1_CIUCLK	4
+#define HI6220_MMC2_CLK		5
+#define HI6220_MMC2_CIUCLK	6
+#define HI6220_USBOTG_HCLK	7
+#define HI6220_CLK_PICOPHY	8
+#define HI6220_HIFI		9
+#define HI6220_DACODEC_PCLK	10
+#define HI6220_EDMAC_ACLK	11
+#define HI6220_CS_ATB		12
+#define HI6220_I2C0_CLK		13
+#define HI6220_I2C1_CLK		14
+#define HI6220_I2C2_CLK		15
+#define HI6220_I2C3_CLK		16
+#define HI6220_UART1_PCLK	17
+#define HI6220_UART2_PCLK	18
+#define HI6220_UART3_PCLK	19
+#define HI6220_UART4_PCLK	20
+#define HI6220_SPI_CLK		21
+#define HI6220_TSENSOR_CLK	22
+#define HI6220_MMU_CLK		23
+#define HI6220_HIFI_SEL		24
+#define HI6220_MMC0_SYSPLL	25
+#define HI6220_MMC1_SYSPLL	26
+#define HI6220_MMC2_SYSPLL	27
+#define HI6220_MMC0_SEL		28
+#define HI6220_MMC1_SEL		29
+#define HI6220_BBPPLL_SEL	30
+#define HI6220_MEDIA_PLL_SRC	31
+#define HI6220_MMC2_SEL		32
+#define HI6220_CS_ATB_SYSPLL	33
+
+/* mux clocks */
+#define HI6220_MMC0_SRC		34
+#define HI6220_MMC0_SMP_IN	35
+#define HI6220_MMC1_SRC		36
+#define HI6220_MMC1_SMP_IN	37
+#define HI6220_MMC2_SRC		38
+#define HI6220_MMC2_SMP_IN	39
+#define HI6220_HIFI_SRC		40
+#define HI6220_UART1_SRC	41
+#define HI6220_UART2_SRC	42
+#define HI6220_UART3_SRC	43
+#define HI6220_UART4_SRC	44
+#define HI6220_MMC0_MUX0	45
+#define HI6220_MMC1_MUX0	46
+#define HI6220_MMC2_MUX0	47
+#define HI6220_MMC0_MUX1	48
+#define HI6220_MMC1_MUX1	49
+#define HI6220_MMC2_MUX1	50
+
+/* divider clocks */
+#define HI6220_CLK_BUS		51
+#define HI6220_MMC0_DIV		52
+#define HI6220_MMC1_DIV		53
+#define HI6220_MMC2_DIV		54
+#define HI6220_HIFI_DIV		55
+#define HI6220_BBPPLL0_DIV	56
+#define HI6220_CS_DAPB		57
+#define HI6220_CS_ATB_DIV	58
+
+#define HI6220_SYS_NR_CLKS	59
+
+/* clk in Hi6220 media controller */
+/* gate clocks */
+#define HI6220_DSI_PCLK		1
+#define HI6220_G3D_PCLK		2
+#define HI6220_ACLK_CODEC_VPU	3
+#define HI6220_ISP_SCLK		4
+#define HI6220_ADE_CORE		5
+#define HI6220_MED_MMU		6
+#define HI6220_CFG_CSI4PHY	7
+#define HI6220_CFG_CSI2PHY	8
+#define HI6220_ISP_SCLK_GATE	9
+#define HI6220_ISP_SCLK_GATE1	10
+#define HI6220_ADE_CORE_GATE	11
+#define HI6220_CODEC_VPU_GATE	12
+#define HI6220_MED_SYSPLL	13
+
+/* mux clocks */
+#define HI6220_1440_1200	14
+#define HI6220_1000_1200	15
+#define HI6220_1000_1440	16
+
+/* divider clocks */
+#define HI6220_CODEC_JPEG	17
+#define HI6220_ISP_SCLK_SRC	18
+#define HI6220_ISP_SCLK1	19
+#define HI6220_ADE_CORE_SRC	20
+#define HI6220_ADE_PIX_SRC	21
+#define HI6220_G3D_CLK		22
+#define HI6220_CODEC_VPU_SRC	23
+
+#define HI6220_MEDIA_NR_CLKS	24
+
+/* clk in Hi6220 power controller */
+/* gate clocks */
+#define HI6220_PLL_GPU_GATE	1
+#define HI6220_PLL1_DDR_GATE	2
+#define HI6220_PLL_DDR_GATE	3
+#define HI6220_PLL_MEDIA_GATE	4
+#define HI6220_PLL0_BBP_GATE	5
+
+/* divider clocks */
+#define HI6220_DDRC_SRC		6
+#define HI6220_DDRC_AXI1	7
+
+#define HI6220_POWER_NR_CLKS	8
+#endif

From 72ea48610d43c59507d9ad39083d40085400ba12 Mon Sep 17 00:00:00 2001
From: Bintian Wang <bintian.wang@huawei.com>
Date: Fri, 29 May 2015 10:08:38 +0800
Subject: [PATCH 088/135] clk: hi6220: Clock driver support for Hisilicon
 hi6220 SoC

Add clock drivers for hi6220 SoC, this driver controls the SoC
registers to supply different clocks to different IPs in the SoC.

We add one divider clock for hi6220 because the divider in hi6220
also has a mask bit but it doesnot obey the rule defined by flag
"CLK_DIVIDER_HIWORD_MASK", we can not get index of the mask bit by
left shift fixed bits (e.g. 16 bits), so we add this divider clock
to handle it.

Signed-off-by: Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
Signed-off-by: Bintian Wang <bintian.wang@huawei.com>
Acked-by: Haojian Zhuang <haojian.zhuang@linaro.org>
Reviewed-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Tested-by: Will Deacon <will.deacon@arm.com>
Tested-by: Tyler Baker <tyler.baker@linaro.org>
Tested-by: Kevin Hilman <khilman@linaro.org>
Signed-off-by: Michael Turquette <mturquette@linaro.org>
---
 drivers/clk/Kconfig                       |   1 +
 drivers/clk/Makefile                      |   4 +-
 drivers/clk/hisilicon/Kconfig             |   6 +
 drivers/clk/hisilicon/Makefile            |   3 +-
 drivers/clk/hisilicon/clk-hi6220.c        | 284 ++++++++++++++++++++++
 drivers/clk/hisilicon/clk.c               |  29 +++
 drivers/clk/hisilicon/clk.h               |  17 ++
 drivers/clk/hisilicon/clkdivider-hi6220.c | 156 ++++++++++++
 8 files changed, 496 insertions(+), 4 deletions(-)
 create mode 100644 drivers/clk/hisilicon/Kconfig
 create mode 100644 drivers/clk/hisilicon/clk-hi6220.c
 create mode 100644 drivers/clk/hisilicon/clkdivider-hi6220.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 9897f353bf1a..8ec04156717b 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -150,6 +150,7 @@ config COMMON_CLK_CDCE706
 	---help---
 	  This driver supports TI CDCE706 programmable 3-PLL clock synthesizer.
 
+source "drivers/clk/hisilicon/Kconfig"
 source "drivers/clk/qcom/Kconfig"
 
 endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 3d00c25382c5..971995428861 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -47,9 +47,7 @@ obj-$(CONFIG_COMMON_CLK_PWM)		+= clk-pwm.o
 obj-$(CONFIG_COMMON_CLK_AT91)		+= at91/
 obj-$(CONFIG_ARCH_BCM_MOBILE)		+= bcm/
 obj-$(CONFIG_ARCH_BERLIN)		+= berlin/
-obj-$(CONFIG_ARCH_HI3xxx)		+= hisilicon/
-obj-$(CONFIG_ARCH_HIP04)		+= hisilicon/
-obj-$(CONFIG_ARCH_HIX5HD2)		+= hisilicon/
+obj-$(CONFIG_ARCH_HISI)			+= hisilicon/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)			+= mmp/
diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig
new file mode 100644
index 000000000000..b4165ba75d9f
--- /dev/null
+++ b/drivers/clk/hisilicon/Kconfig
@@ -0,0 +1,6 @@
+config COMMON_CLK_HI6220
+	bool "Hi6220 Clock Driver"
+	depends on ARCH_HISI || COMPILE_TEST
+	default ARCH_HISI
+	help
+	  Build the Hisilicon Hi6220 clock driver based on the common clock framework.
diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
index 038c02f4d0e7..48f0116a032a 100644
--- a/drivers/clk/hisilicon/Makefile
+++ b/drivers/clk/hisilicon/Makefile
@@ -2,8 +2,9 @@
 # Hisilicon Clock specific Makefile
 #
 
-obj-y	+= clk.o clkgate-separated.o
+obj-y	+= clk.o clkgate-separated.o clkdivider-hi6220.o
 
 obj-$(CONFIG_ARCH_HI3xxx)	+= clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)	+= clk-hip04.o
 obj-$(CONFIG_ARCH_HIX5HD2)	+= clk-hix5hd2.o
+obj-$(CONFIG_COMMON_CLK_HI6220)	+= clk-hi6220.o
diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
new file mode 100644
index 000000000000..4563343b6420
--- /dev/null
+++ b/drivers/clk/hisilicon/clk-hi6220.c
@@ -0,0 +1,284 @@
+/*
+ * Hisilicon Hi6220 clock driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/hi6220-clock.h>
+
+#include "clk.h"
+
+
+/* clocks in AO (always on) controller */
+static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
+	{ HI6220_REF32K,	"ref32k",	NULL, CLK_IS_ROOT, 32764,     },
+	{ HI6220_CLK_TCXO,	"clk_tcxo",	NULL, CLK_IS_ROOT, 19200000,  },
+	{ HI6220_MMC1_PAD,	"mmc1_pad",	NULL, CLK_IS_ROOT, 100000000, },
+	{ HI6220_MMC2_PAD,	"mmc2_pad",	NULL, CLK_IS_ROOT, 100000000, },
+	{ HI6220_MMC0_PAD,	"mmc0_pad",	NULL, CLK_IS_ROOT, 200000000, },
+	{ HI6220_PLL_BBP,	"bbppll0",	NULL, CLK_IS_ROOT, 245760000, },
+	{ HI6220_PLL_GPU,	"gpupll",	NULL, CLK_IS_ROOT, 1000000000,},
+	{ HI6220_PLL1_DDR,	"ddrpll1",	NULL, CLK_IS_ROOT, 1066000000,},
+	{ HI6220_PLL_SYS,	"syspll",	NULL, CLK_IS_ROOT, 1200000000,},
+	{ HI6220_PLL_SYS_MEDIA,	"media_syspll",	NULL, CLK_IS_ROOT, 1200000000,},
+	{ HI6220_DDR_SRC,	"ddr_sel_src",  NULL, CLK_IS_ROOT, 1200000000,},
+	{ HI6220_PLL_MEDIA,	"media_pll",    NULL, CLK_IS_ROOT, 1440000000,},
+	{ HI6220_PLL_DDR,	"ddrpll0",      NULL, CLK_IS_ROOT, 1600000000,},
+};
+
+static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = {
+	{ HI6220_300M,         "clk_300m",    "syspll",          1, 4, 0, },
+	{ HI6220_150M,         "clk_150m",    "clk_300m",        1, 2, 0, },
+	{ HI6220_PICOPHY_SRC,  "picophy_src", "clk_150m",        1, 4, 0, },
+	{ HI6220_MMC0_SRC_SEL, "mmc0srcsel",  "mmc0_sel",        1, 8, 0, },
+	{ HI6220_MMC1_SRC_SEL, "mmc1srcsel",  "mmc1_sel",        1, 8, 0, },
+	{ HI6220_MMC2_SRC_SEL, "mmc2srcsel",  "mmc2_sel",        1, 8, 0, },
+	{ HI6220_VPU_CODEC,    "vpucodec",    "codec_jpeg_aclk", 1, 2, 0, },
+	{ HI6220_MMC0_SMP,     "mmc0_sample", "mmc0_sel",        1, 8, 0, },
+	{ HI6220_MMC1_SMP,     "mmc1_sample", "mmc1_sel",        1, 8, 0, },
+	{ HI6220_MMC2_SMP,     "mmc2_sample", "mmc2_sel",        1, 8, 0, },
+};
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
+	{ HI6220_WDT0_PCLK,   "wdt0_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, },
+	{ HI6220_WDT1_PCLK,   "wdt1_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, },
+	{ HI6220_WDT2_PCLK,   "wdt2_pclk",   "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, },
+	{ HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, },
+	{ HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, },
+	{ HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, },
+	{ HI6220_TIMER3_PCLK, "timer3_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 18, 0, },
+	{ HI6220_TIMER4_PCLK, "timer4_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 19, 0, },
+	{ HI6220_TIMER5_PCLK, "timer5_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 20, 0, },
+	{ HI6220_TIMER6_PCLK, "timer6_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 21, 0, },
+	{ HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, },
+	{ HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, },
+	{ HI6220_UART0_PCLK,  "uart0_pclk",  "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, },
+};
+
+static void __init hi6220_clk_ao_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data_ao;
+
+	clk_data_ao = hisi_clk_init(np, HI6220_AO_NR_CLKS);
+	if (!clk_data_ao)
+		return;
+
+	hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
+				ARRAY_SIZE(hi6220_fixed_rate_clks), clk_data_ao);
+
+	hisi_clk_register_fixed_factor(hi6220_fixed_factor_clks,
+				ARRAY_SIZE(hi6220_fixed_factor_clks), clk_data_ao);
+
+	hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
+				ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data_ao);
+}
+CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-aoctrl", hi6220_clk_ao_init);
+
+
+/* clocks in sysctrl */
+static const char *mmc0_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
+static const char *mmc0_mux1_p[] __initdata = { "mmc0_mux0", "pll_media_gate", };
+static const char *mmc0_src_p[] __initdata = { "mmc0srcsel", "mmc0_div", };
+static const char *mmc1_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
+static const char *mmc1_mux1_p[] __initdata = { "mmc1_mux0", "pll_media_gate", };
+static const char *mmc1_src_p[]  __initdata = { "mmc1srcsel", "mmc1_div", };
+static const char *mmc2_mux0_p[] __initdata = { "pll_ddr_gate", "syspll", };
+static const char *mmc2_mux1_p[] __initdata = { "mmc2_mux0", "pll_media_gate", };
+static const char *mmc2_src_p[]  __initdata = { "mmc2srcsel", "mmc2_div", };
+static const char *mmc0_sample_in[] __initdata = { "mmc0_sample", "mmc0_pad", };
+static const char *mmc1_sample_in[] __initdata = { "mmc1_sample", "mmc1_pad", };
+static const char *mmc2_sample_in[] __initdata = { "mmc2_sample", "mmc2_pad", };
+static const char *uart1_src[] __initdata = { "clk_tcxo", "clk_150m", };
+static const char *uart2_src[] __initdata = { "clk_tcxo", "clk_150m", };
+static const char *uart3_src[] __initdata = { "clk_tcxo", "clk_150m", };
+static const char *uart4_src[] __initdata = { "clk_tcxo", "clk_150m", };
+static const char *hifi_src[] __initdata = { "syspll", "pll_media_gate", };
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
+	{ HI6220_MMC0_CLK,      "mmc0_clk",      "mmc0_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
+	{ HI6220_MMC0_CIUCLK,   "mmc0_ciuclk",   "mmc0_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 0,  0, },
+	{ HI6220_MMC1_CLK,      "mmc1_clk",      "mmc1_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
+	{ HI6220_MMC1_CIUCLK,   "mmc1_ciuclk",   "mmc1_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 1,  0, },
+	{ HI6220_MMC2_CLK,      "mmc2_clk",      "mmc2_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
+	{ HI6220_MMC2_CIUCLK,   "mmc2_ciuclk",   "mmc2_smp_in",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 2,  0, },
+	{ HI6220_USBOTG_HCLK,   "usbotg_hclk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 4,  0, },
+	{ HI6220_CLK_PICOPHY,   "clk_picophy",   "cs_dapb",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x200, 5,  0, },
+	{ HI6220_HIFI,          "hifi_clk",      "hifi_div",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 0,  0, },
+	{ HI6220_DACODEC_PCLK,  "dacodec_pclk",  "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x210, 5,  0, },
+	{ HI6220_EDMAC_ACLK,    "edmac_aclk",    "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x220, 2,  0, },
+	{ HI6220_CS_ATB,        "cs_atb",        "cs_atb_div",     CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 0,  0, },
+	{ HI6220_I2C0_CLK,      "i2c0_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 1,  0, },
+	{ HI6220_I2C1_CLK,      "i2c1_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 2,  0, },
+	{ HI6220_I2C2_CLK,      "i2c2_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 3,  0, },
+	{ HI6220_I2C3_CLK,      "i2c3_clk",      "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 4,  0, },
+	{ HI6220_UART1_PCLK,    "uart1_pclk",    "uart1_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 5,  0, },
+	{ HI6220_UART2_PCLK,    "uart2_pclk",    "uart2_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 6,  0, },
+	{ HI6220_UART3_PCLK,    "uart3_pclk",    "uart3_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 7,  0, },
+	{ HI6220_UART4_PCLK,    "uart4_pclk",    "uart4_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8,  0, },
+	{ HI6220_SPI_CLK,       "spi_clk",       "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, },
+	{ HI6220_TSENSOR_CLK,   "tsensor_clk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 12, 0, },
+	{ HI6220_MMU_CLK,       "mmu_clk",       "ddrc_axi1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
+	{ HI6220_HIFI_SEL,      "hifi_sel",      "hifi_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0,  0, },
+	{ HI6220_MMC0_SYSPLL,   "mmc0_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1,  0, },
+	{ HI6220_MMC1_SYSPLL,   "mmc1_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 2,  0, },
+	{ HI6220_MMC2_SYSPLL,   "mmc2_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 3,  0, },
+	{ HI6220_MMC0_SEL,      "mmc0_sel",      "mmc0_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 6,  0, },
+	{ HI6220_MMC1_SEL,      "mmc1_sel",      "mmc1_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 7,  0, },
+	{ HI6220_BBPPLL_SEL,    "bbppll_sel",    "pll0_bbp_gate",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9,  0, },
+	{ HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
+	{ HI6220_MMC2_SEL,      "mmc2_sel",      "mmc2_mux1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
+	{ HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
+};
+
+static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {
+	{ HI6220_MMC0_SRC,    "mmc0_src",    mmc0_src_p,     ARRAY_SIZE(mmc0_src_p),     CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
+	{ HI6220_MMC0_SMP_IN, "mmc0_smp_in", mmc0_sample_in, ARRAY_SIZE(mmc0_sample_in), CLK_SET_RATE_PARENT, 0x4,   0,  1, 0, },
+	{ HI6220_MMC1_SRC,    "mmc1_src",    mmc1_src_p,     ARRAY_SIZE(mmc1_src_p),     CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
+	{ HI6220_MMC1_SMP_IN, "mmc1_smp_in", mmc1_sample_in, ARRAY_SIZE(mmc1_sample_in), CLK_SET_RATE_PARENT, 0x4,   2,  1, 0, },
+	{ HI6220_MMC2_SRC,    "mmc2_src",    mmc2_src_p,     ARRAY_SIZE(mmc2_src_p),     CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
+	{ HI6220_MMC2_SMP_IN, "mmc2_smp_in", mmc2_sample_in, ARRAY_SIZE(mmc2_sample_in), CLK_SET_RATE_PARENT, 0x4,   4,  1, 0, },
+	{ HI6220_HIFI_SRC,    "hifi_src",    hifi_src,       ARRAY_SIZE(hifi_src),       CLK_SET_RATE_PARENT, 0x400, 0,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART1_SRC,   "uart1_src",   uart1_src,      ARRAY_SIZE(uart1_src),      CLK_SET_RATE_PARENT, 0x400, 1,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART2_SRC,   "uart2_src",   uart2_src,      ARRAY_SIZE(uart2_src),      CLK_SET_RATE_PARENT, 0x400, 2,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART3_SRC,   "uart3_src",   uart3_src,      ARRAY_SIZE(uart3_src),      CLK_SET_RATE_PARENT, 0x400, 3,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_UART4_SRC,   "uart4_src",   uart4_src,      ARRAY_SIZE(uart4_src),      CLK_SET_RATE_PARENT, 0x400, 4,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC0_MUX0,   "mmc0_mux0",   mmc0_mux0_p,    ARRAY_SIZE(mmc0_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 5,  1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC1_MUX0,   "mmc1_mux0",   mmc1_mux0_p,    ARRAY_SIZE(mmc1_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 11, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC2_MUX0,   "mmc2_mux0",   mmc2_mux0_p,    ARRAY_SIZE(mmc2_mux0_p),    CLK_SET_RATE_PARENT, 0x400, 12, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC0_MUX1,   "mmc0_mux1",   mmc0_mux1_p,    ARRAY_SIZE(mmc0_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 13, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC1_MUX1,   "mmc1_mux1",   mmc1_mux1_p,    ARRAY_SIZE(mmc1_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 14, 1, CLK_MUX_HIWORD_MASK,},
+	{ HI6220_MMC2_MUX1,   "mmc2_mux1",   mmc2_mux1_p,    ARRAY_SIZE(mmc2_mux1_p),    CLK_SET_RATE_PARENT, 0x400, 15, 1, CLK_MUX_HIWORD_MASK,},
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_sys[] __initdata = {
+	{ HI6220_CLK_BUS,     "clk_bus",     "clk_300m",      CLK_SET_RATE_PARENT, 0x490, 0,  4, 7, },
+	{ HI6220_MMC0_DIV,    "mmc0_div",    "mmc0_syspll",   CLK_SET_RATE_PARENT, 0x494, 0,  6, 7, },
+	{ HI6220_MMC1_DIV,    "mmc1_div",    "mmc1_syspll",   CLK_SET_RATE_PARENT, 0x498, 0,  6, 7, },
+	{ HI6220_MMC2_DIV,    "mmc2_div",    "mmc2_syspll",   CLK_SET_RATE_PARENT, 0x49c, 0,  6, 7, },
+	{ HI6220_HIFI_DIV,    "hifi_div",    "hifi_sel",      CLK_SET_RATE_PARENT, 0x4a0, 0,  4, 7, },
+	{ HI6220_BBPPLL0_DIV, "bbppll0_div", "bbppll_sel",    CLK_SET_RATE_PARENT, 0x4a0, 8,  6, 15,},
+	{ HI6220_CS_DAPB,     "cs_dapb",     "picophy_src",   CLK_SET_RATE_PARENT, 0x4a0, 24, 2, 31,},
+	{ HI6220_CS_ATB_DIV,  "cs_atb_div",  "cs_atb_syspll", CLK_SET_RATE_PARENT, 0x4a4, 0,  4, 7, },
+};
+
+static void __init hi6220_clk_sys_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_SYS_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_gate_sep(hi6220_separated_gate_clks_sys,
+			ARRAY_SIZE(hi6220_separated_gate_clks_sys), clk_data);
+
+	hisi_clk_register_mux(hi6220_mux_clks_sys,
+			ARRAY_SIZE(hi6220_mux_clks_sys), clk_data);
+
+	hi6220_clk_register_divider(hi6220_div_clks_sys,
+			ARRAY_SIZE(hi6220_div_clks_sys), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_sys, "hisilicon,hi6220-sysctrl", hi6220_clk_sys_init);
+
+
+/* clocks in media controller */
+static const char *clk_1000_1200_src[] __initdata = { "pll_gpu_gate", "media_syspll_src", };
+static const char *clk_1440_1200_src[] __initdata = { "media_syspll_src", "media_pll_src", };
+static const char *clk_1000_1440_src[] __initdata = { "pll_gpu_gate", "media_pll_src", };
+
+static struct hisi_gate_clock hi6220_separated_gate_clks_media[] __initdata = {
+	{ HI6220_DSI_PCLK,       "dsi_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 0,  0, },
+	{ HI6220_G3D_PCLK,       "g3d_pclk",         "vpucodec",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 1,  0, },
+	{ HI6220_ACLK_CODEC_VPU, "aclk_codec_vpu",   "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 3,  0, },
+	{ HI6220_ISP_SCLK,       "isp_sclk",         "isp_sclk_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 5,  0, },
+	{ HI6220_ADE_CORE,	 "ade_core",	     "ade_core_src",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 6,  0, },
+	{ HI6220_MED_MMU,        "media_mmu",        "mmu_clk",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 8,  0, },
+	{ HI6220_CFG_CSI4PHY,    "cfg_csi4phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 9,  0, },
+	{ HI6220_CFG_CSI2PHY,    "cfg_csi2phy",      "clk_tcxo",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 10, 0, },
+	{ HI6220_ISP_SCLK_GATE,  "isp_sclk_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 11, 0, },
+	{ HI6220_ISP_SCLK_GATE1, "isp_sclk_gate1",   "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 12, 0, },
+	{ HI6220_ADE_CORE_GATE,  "ade_core_gate",    "media_pll_src", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 14, 0, },
+	{ HI6220_CODEC_VPU_GATE, "codec_vpu_gate",   "clk_1000_1440", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 15, 0, },
+	{ HI6220_MED_SYSPLL,     "media_syspll_src", "media_syspll",  CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x520, 17, 0, },
+};
+
+static struct hisi_mux_clock hi6220_mux_clks_media[] __initdata = {
+	{ HI6220_1440_1200, "clk_1440_1200", clk_1440_1200_src, ARRAY_SIZE(clk_1440_1200_src), CLK_SET_RATE_PARENT, 0x51c, 0, 1, 0, },
+	{ HI6220_1000_1200, "clk_1000_1200", clk_1000_1200_src, ARRAY_SIZE(clk_1000_1200_src), CLK_SET_RATE_PARENT, 0x51c, 1, 1, 0, },
+	{ HI6220_1000_1440, "clk_1000_1440", clk_1000_1440_src, ARRAY_SIZE(clk_1000_1440_src), CLK_SET_RATE_PARENT, 0x51c, 6, 1, 0, },
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_media[] __initdata = {
+	{ HI6220_CODEC_JPEG,    "codec_jpeg_aclk", "media_pll_src",  CLK_SET_RATE_PARENT, 0xcbc, 0,  4, 23, },
+	{ HI6220_ISP_SCLK_SRC,  "isp_sclk_src",    "isp_sclk_gate",  CLK_SET_RATE_PARENT, 0xcbc, 8,  4, 15, },
+	{ HI6220_ISP_SCLK1,     "isp_sclk1",       "isp_sclk_gate1", CLK_SET_RATE_PARENT, 0xcbc, 24, 4, 31, },
+	{ HI6220_ADE_CORE_SRC,  "ade_core_src",    "ade_core_gate",  CLK_SET_RATE_PARENT, 0xcc0, 16, 3, 23, },
+	{ HI6220_ADE_PIX_SRC,   "ade_pix_src",     "clk_1440_1200",  CLK_SET_RATE_PARENT, 0xcc0, 24, 6, 31, },
+	{ HI6220_G3D_CLK,       "g3d_clk",         "clk_1000_1200",  CLK_SET_RATE_PARENT, 0xcc4, 8,  4, 15, },
+	{ HI6220_CODEC_VPU_SRC, "codec_vpu_src",   "codec_vpu_gate", CLK_SET_RATE_PARENT, 0xcc4, 24, 6, 31, },
+};
+
+static void __init hi6220_clk_media_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_MEDIA_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_gate_sep(hi6220_separated_gate_clks_media,
+				ARRAY_SIZE(hi6220_separated_gate_clks_media), clk_data);
+
+	hisi_clk_register_mux(hi6220_mux_clks_media,
+				ARRAY_SIZE(hi6220_mux_clks_media), clk_data);
+
+	hi6220_clk_register_divider(hi6220_div_clks_media,
+				ARRAY_SIZE(hi6220_div_clks_media), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_media, "hisilicon,hi6220-mediactrl", hi6220_clk_media_init);
+
+
+/* clocks in pmctrl */
+static struct hisi_gate_clock hi6220_gate_clks_power[] __initdata = {
+	{ HI6220_PLL_GPU_GATE,   "pll_gpu_gate",   "gpupll",    CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x8,  0,  0, },
+	{ HI6220_PLL1_DDR_GATE,  "pll1_ddr_gate",  "ddrpll1",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x10, 0,  0, },
+	{ HI6220_PLL_DDR_GATE,   "pll_ddr_gate",   "ddrpll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x18, 0,  0, },
+	{ HI6220_PLL_MEDIA_GATE, "pll_media_gate", "media_pll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x38, 0,  0, },
+	{ HI6220_PLL0_BBP_GATE,  "pll0_bbp_gate",  "bbppll0",   CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x48, 0,  0, },
+};
+
+static struct hi6220_divider_clock hi6220_div_clks_power[] __initdata = {
+	{ HI6220_DDRC_SRC,  "ddrc_src",  "ddr_sel_src", CLK_SET_RATE_PARENT, 0x5a8, 0, 4, 0, },
+	{ HI6220_DDRC_AXI1, "ddrc_axi1", "ddrc_src",    CLK_SET_RATE_PARENT, 0x5a8, 8, 2, 0, },
+};
+
+static void __init hi6220_clk_power_init(struct device_node *np)
+{
+	struct hisi_clock_data *clk_data;
+
+	clk_data = hisi_clk_init(np, HI6220_POWER_NR_CLKS);
+	if (!clk_data)
+		return;
+
+	hisi_clk_register_gate(hi6220_gate_clks_power,
+				ARRAY_SIZE(hi6220_gate_clks_power), clk_data);
+
+	hi6220_clk_register_divider(hi6220_div_clks_power,
+				ARRAY_SIZE(hi6220_div_clks_power), clk_data);
+}
+CLK_OF_DECLARE(hi6220_clk_power, "hisilicon,hi6220-pmctrl", hi6220_clk_power_init);
diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
index a078e84f7b05..c90a89739b03 100644
--- a/drivers/clk/hisilicon/clk.c
+++ b/drivers/clk/hisilicon/clk.c
@@ -232,3 +232,32 @@ void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
 		data->clk_data.clks[clks[i].id] = clk;
 	}
 }
+
+void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
+					int nums, struct hisi_clock_data *data)
+{
+	struct clk *clk;
+	void __iomem *base = data->base;
+	int i;
+
+	for (i = 0; i < nums; i++) {
+		clk = hi6220_register_clkdiv(NULL, clks[i].name,
+						clks[i].parent_name,
+						clks[i].flags,
+						base + clks[i].offset,
+						clks[i].shift,
+						clks[i].width,
+						clks[i].mask_bit,
+						&hisi_clk_lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n",
+			       __func__, clks[i].name);
+			continue;
+		}
+
+		if (clks[i].alias)
+			clk_register_clkdev(clk, clks[i].alias, NULL);
+
+		data->clk_data.clks[clks[i].id] = clk;
+	}
+}
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index 6b6f99448e01..21b403b3423a 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -79,6 +79,18 @@ struct hisi_divider_clock {
 	const char		*alias;
 };
 
+struct hi6220_divider_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	unsigned long		offset;
+	u8			shift;
+	u8			width;
+	u32			mask_bit;
+	const char		*alias;
+};
+
 struct hisi_gate_clock {
 	unsigned int		id;
 	const char		*name;
@@ -94,6 +106,9 @@ struct clk *hisi_register_clkgate_sep(struct device *, const char *,
 				const char *, unsigned long,
 				void __iomem *, u8,
 				u8, spinlock_t *);
+struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
+	const char *parent_name, unsigned long flags, void __iomem *reg,
+	u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
 
 struct hisi_clock_data *hisi_clk_init(struct device_node *, int);
 void hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
@@ -108,4 +123,6 @@ void hisi_clk_register_gate(struct hisi_gate_clock *,
 				int, struct hisi_clock_data *);
 void hisi_clk_register_gate_sep(struct hisi_gate_clock *,
 				int, struct hisi_clock_data *);
+void hi6220_clk_register_divider(struct hi6220_divider_clock *,
+				int, struct hisi_clock_data *);
 #endif	/* __HISI_CLK_H */
diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
new file mode 100644
index 000000000000..113eee8ed23a
--- /dev/null
+++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
@@ -0,0 +1,156 @@
+/*
+ * Hisilicon hi6220 SoC divider clock driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Bintian Wang <bintian.wang@huawei.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+
+#define div_mask(width)	((1 << (width)) - 1)
+
+/**
+ * struct hi6220_clk_divider - divider clock for hi6220
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	register containing divider
+ * @shift:	shift to the divider bit field
+ * @width:	width of the divider bit field
+ * @mask:	mask for setting divider rate
+ * @table:	the div table that the divider supports
+ * @lock:	register lock
+ */
+struct hi6220_clk_divider {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u8		shift;
+	u8		width;
+	u32		mask;
+	const struct clk_div_table *table;
+	spinlock_t	*lock;
+};
+
+#define to_hi6220_clk_divider(_hw)	\
+	container_of(_hw, struct hi6220_clk_divider, hw)
+
+static unsigned long hi6220_clkdiv_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	unsigned int val;
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+	val = readl_relaxed(dclk->reg) >> dclk->shift;
+	val &= div_mask(dclk->width);
+
+	return divider_recalc_rate(hw, parent_rate, val, dclk->table,
+				   CLK_DIVIDER_ROUND_CLOSEST);
+}
+
+static long hi6220_clkdiv_round_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long *prate)
+{
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+	return divider_round_rate(hw, rate, prate, dclk->table,
+				  dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
+}
+
+static int hi6220_clkdiv_set_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long parent_rate)
+{
+	int value;
+	unsigned long flags = 0;
+	u32 data;
+	struct hi6220_clk_divider *dclk = to_hi6220_clk_divider(hw);
+
+	value = divider_get_val(rate, parent_rate, dclk->table,
+				dclk->width, CLK_DIVIDER_ROUND_CLOSEST);
+
+	if (dclk->lock)
+		spin_lock_irqsave(dclk->lock, flags);
+
+	data = readl_relaxed(dclk->reg);
+	data &= ~(div_mask(dclk->width) << dclk->shift);
+	data |= value << dclk->shift;
+	data |= dclk->mask;
+
+	writel_relaxed(data, dclk->reg);
+
+	if (dclk->lock)
+		spin_unlock_irqrestore(dclk->lock, flags);
+
+	return 0;
+}
+
+static const struct clk_ops hi6220_clkdiv_ops = {
+	.recalc_rate = hi6220_clkdiv_recalc_rate,
+	.round_rate = hi6220_clkdiv_round_rate,
+	.set_rate = hi6220_clkdiv_set_rate,
+};
+
+struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
+	const char *parent_name, unsigned long flags, void __iomem *reg,
+	u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
+{
+	struct hi6220_clk_divider *div;
+	struct clk *clk;
+	struct clk_init_data init;
+	struct clk_div_table *table;
+	u32 max_div, min_div;
+	int i;
+
+	/* allocate the divider */
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
+	/* Init the divider table */
+	max_div = div_mask(width) + 1;
+	min_div = 1;
+
+	table = kcalloc(max_div + 1, sizeof(*table), GFP_KERNEL);
+	if (!table) {
+		kfree(div);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	for (i = 0; i < max_div; i++) {
+		table[i].div = min_div + i;
+		table[i].val = table[i].div - 1;
+	}
+
+	init.name = name;
+	init.ops = &hi6220_clkdiv_ops;
+	init.flags = flags;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+
+	/* struct hi6220_clk_divider assignments */
+	div->reg = reg;
+	div->shift = shift;
+	div->width = width;
+	div->mask = mask_bit ? BIT(mask_bit) : 0;
+	div->lock = lock;
+	div->hw.init = &init;
+	div->table = table;
+
+	/* register the clock */
+	clk = clk_register(dev, &div->hw);
+	if (IS_ERR(clk)) {
+		kfree(table);
+		kfree(div);
+	}
+
+	return clk;
+}

From 4d52b2acefdfceae0e47ed08324a96f511dc80b1 Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon@free-electrons.com>
Date: Tue, 26 May 2015 14:42:57 +0200
Subject: [PATCH 089/135] clk: mvebu: add missing CESA gate clk

Even if not documented in the datasheet, the Armada 370 SoC can actually
gate the CESA (crypto engine) clock.
Add an entry in the gating_desc table to be able to reference the CESA
gateclk in the crypto node.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Michael Turquette <mturquette@linaro.org>
---
 Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt | 1 +
 drivers/clk/mvebu/armada-370.c                                | 1 +
 2 files changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
index 31c7c0c1ce8f..660e64912cce 100644
--- a/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
+++ b/Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
@@ -19,6 +19,7 @@ ID	Clock	Peripheral
 9	pex1	PCIe Cntrl 1
 15	sata0	SATA Host 0
 17	sdio	SDHCI Host
+23	crypto	CESA (crypto engine)
 25	tdm	Time Division Mplx
 28	ddr	DDR Cntrl
 30	sata1	SATA Host 0
diff --git a/drivers/clk/mvebu/armada-370.c b/drivers/clk/mvebu/armada-370.c
index 756f0f39d6a3..c19fd77e6c27 100644
--- a/drivers/clk/mvebu/armada-370.c
+++ b/drivers/clk/mvebu/armada-370.c
@@ -163,6 +163,7 @@ static const struct clk_gating_soc_desc a370_gating_desc[] __initconst = {
 	{ "pex1", "pex1_en", 9, 0 },
 	{ "sata0", NULL, 15, 0 },
 	{ "sdio", NULL, 17, 0 },
+	{ "crypto", NULL, 23, 0 },
 	{ "tdm", NULL, 25, 0 },
 	{ "ddr", NULL, 28, CLK_IGNORE_UNUSED },
 	{ "sata1", NULL, 30, 0 },

From 19fbbbbcd3a3a8e307a4768784166abf7b55b779 Mon Sep 17 00:00:00 2001
From: Mike Looijmans <mike.looijmans@topic.nl>
Date: Wed, 3 Jun 2015 07:25:19 +0200
Subject: [PATCH 090/135] Add TI CDCE925 I2C controlled clock synthesizer
 driver

This driver supports the TI CDCE925 programmable clock synthesizer.
The chip contains two PLLs with spread-spectrum clocking support and
five output dividers. The driver only supports the following setup,
and uses a fixed setting for the output muxes:
  Y1 is derived from the input clock
  Y2 and Y3 derive from PLL1
  Y4 and Y5 derive from PLL2
Given a target output frequency, the driver will set the PLL and
divider to best approximate the desired output.

Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl>
Signed-off-by: Michael Turquette <mturquette@linaro.org>
---
 .../devicetree/bindings/clock/ti,cdce925.txt  |  42 +
 drivers/clk/Kconfig                           |  17 +
 drivers/clk/Makefile                          |   1 +
 drivers/clk/clk-cdce925.c                     | 749 ++++++++++++++++++
 4 files changed, 809 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/ti,cdce925.txt
 create mode 100644 drivers/clk/clk-cdce925.c

diff --git a/Documentation/devicetree/bindings/clock/ti,cdce925.txt b/Documentation/devicetree/bindings/clock/ti,cdce925.txt
new file mode 100644
index 000000000000..4c7669ad681b
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti,cdce925.txt
@@ -0,0 +1,42 @@
+Binding for TO CDCE925 programmable I2C clock synthesizers.
+
+Reference
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] http://www.ti.com/product/cdce925
+
+The driver provides clock sources for each output Y1 through Y5.
+
+Required properties:
+ - compatible: Shall be "ti,cdce925"
+ - reg: I2C device address.
+ - clocks: Points to a fixed parent clock that provides the input frequency.
+ - #clock-cells: From common clock bindings: Shall be 1.
+
+Optional properties:
+ - xtal-load-pf: Crystal load-capacitor value to fine-tune performance on a
+                 board, or to compensate for external influences.
+
+For both PLL1 and PLL2 an optional child node can be used to specify spread
+spectrum clocking parameters for a board.
+  - spread-spectrum: SSC mode as defined in the data sheet.
+  - spread-spectrum-center: Use "centered" mode instead of "max" mode. When
+    present, the clock runs at the requested frequency on average. Otherwise
+    the requested frequency is the maximum value of the SCC range.
+
+
+Example:
+
+	clockgen: cdce925pw@64 {
+		compatible = "cdce925";
+		reg = <0x64>;
+		clocks = <&xtal_27Mhz>;
+		#clock-cells = <1>;
+		xtal-load-pf = <5>;
+		/* PLL options to get SSC 1% centered */
+		PLL2 {
+			spread-spectrum = <4>;
+			spread-spectrum-center;
+		};
+	};
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 67e3a84d2805..e33ff4e3e18d 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -78,6 +78,23 @@ config COMMON_CLK_SI570
 	  This driver supports Silicon Labs 570/571/598/599 programmable
 	  clock generators.
 
+config COMMON_CLK_CDCE925
+	tristate "Clock driver for TI CDCE925 devices"
+	depends on I2C
+	depends on OF
+	select REGMAP_I2C
+	help
+	---help---
+	  This driver supports the TI CDCE925 programmable clock synthesizer.
+	  The chip contains two PLLs with spread-spectrum clocking support and
+	  five output dividers. The driver only supports the following setup,
+	  and uses a fixed setting for the output muxes.
+	  Y1 is derived from the input clock
+	  Y2 and Y3 derive from PLL1
+	  Y4 and Y5 derive from PLL2
+	  Given a target output frequency, the driver will set the PLL and
+	  divider to best approximate the desired output.
+
 config COMMON_CLK_S2MPS11
 	tristate "Clock driver for S2MPS1X/S5M8767 MFD"
 	depends on MFD_SEC_CORE
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d965b3f6a372..00ae2de0803a 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_COMMON_CLK_RK808)		+= clk-rk808.o
 obj-$(CONFIG_COMMON_CLK_S2MPS11)	+= clk-s2mps11.o
 obj-$(CONFIG_COMMON_CLK_SI5351)		+= clk-si5351.o
 obj-$(CONFIG_COMMON_CLK_SI570)		+= clk-si570.o
+obj-$(CONFIG_COMMON_CLK_CDCE925)	+= clk-cdce925.o
 obj-$(CONFIG_CLK_TWL6040)		+= clk-twl6040.o
 obj-$(CONFIG_ARCH_U300)			+= clk-u300.o
 obj-$(CONFIG_ARCH_VT8500)		+= clk-vt8500.o
diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c
new file mode 100644
index 000000000000..56b870d331a1
--- /dev/null
+++ b/drivers/clk/clk-cdce925.c
@@ -0,0 +1,749 @@
+/*
+ * Driver for TI Dual PLL CDCE925 clock synthesizer
+ *
+ * This driver always connects the Y1 to the input clock, Y2/Y3 to PLL1
+ * and Y4/Y5 to PLL2. PLL frequency is set on a first-come-first-serve
+ * basis. Clients can directly request any frequency that the chip can
+ * deliver using the standard clk framework. In addition, the device can
+ * be configured and activated via the devicetree.
+ *
+ * Copyright (C) 2014, Topic Embedded Products
+ * Licenced under GPL
+ */
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/gcd.h>
+
+/* The chip has 2 PLLs which can be routed through dividers to 5 outputs.
+ * Model this as 2 PLL clocks which are parents to the outputs.
+ */
+#define NUMBER_OF_PLLS	2
+#define NUMBER_OF_OUTPUTS	5
+
+#define CDCE925_REG_GLOBAL1	0x01
+#define CDCE925_REG_Y1SPIPDIVH	0x02
+#define CDCE925_REG_PDIVL	0x03
+#define CDCE925_REG_XCSEL	0x05
+/* PLL parameters start at 0x10, steps of 0x10 */
+#define CDCE925_OFFSET_PLL	0x10
+/* Add CDCE925_OFFSET_PLL * (pll) to these registers before sending */
+#define CDCE925_PLL_MUX_OUTPUTS	0x14
+#define CDCE925_PLL_MULDIV	0x18
+
+#define CDCE925_PLL_FREQUENCY_MIN	 80000000ul
+#define CDCE925_PLL_FREQUENCY_MAX	230000000ul
+struct clk_cdce925_chip;
+
+struct clk_cdce925_output {
+	struct clk_hw hw;
+	struct clk_cdce925_chip *chip;
+	u8 index;
+	u16 pdiv; /* 1..127 for Y2-Y5; 1..1023 for Y1 */
+};
+#define to_clk_cdce925_output(_hw) \
+	container_of(_hw, struct clk_cdce925_output, hw)
+
+struct clk_cdce925_pll {
+	struct clk_hw hw;
+	struct clk_cdce925_chip *chip;
+	u8 index;
+	u16 m;   /* 1..511 */
+	u16 n;   /* 1..4095 */
+};
+#define to_clk_cdce925_pll(_hw)	container_of(_hw, struct clk_cdce925_pll, hw)
+
+struct clk_cdce925_chip {
+	struct regmap *regmap;
+	struct i2c_client *i2c_client;
+	struct clk_cdce925_pll pll[NUMBER_OF_PLLS];
+	struct clk_cdce925_output clk[NUMBER_OF_OUTPUTS];
+	struct clk *dt_clk[NUMBER_OF_OUTPUTS];
+	struct clk_onecell_data onecell;
+};
+
+/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
+
+static unsigned long cdce925_pll_calculate_rate(unsigned long parent_rate,
+	u16 n, u16 m)
+{
+	if ((!m || !n) || (m == n))
+		return parent_rate; /* In bypass mode runs at same frequency */
+	return mult_frac(parent_rate, (unsigned long)n, (unsigned long)m);
+}
+
+static unsigned long cdce925_pll_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	/* Output frequency of PLL is Fout = (Fin/Pdiv)*(N/M) */
+	struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
+
+	return cdce925_pll_calculate_rate(parent_rate, data->n, data->m);
+}
+
+static void cdce925_pll_find_rate(unsigned long rate,
+		unsigned long parent_rate, u16 *n, u16 *m)
+{
+	unsigned long un;
+	unsigned long um;
+	unsigned long g;
+
+	if (rate <= parent_rate) {
+		/* Can always deliver parent_rate in bypass mode */
+		rate = parent_rate;
+		*n = 0;
+		*m = 0;
+	} else {
+		/* In PLL mode, need to apply min/max range */
+		if (rate < CDCE925_PLL_FREQUENCY_MIN)
+			rate = CDCE925_PLL_FREQUENCY_MIN;
+		else if (rate > CDCE925_PLL_FREQUENCY_MAX)
+			rate = CDCE925_PLL_FREQUENCY_MAX;
+
+		g = gcd(rate, parent_rate);
+		um = parent_rate / g;
+		un = rate / g;
+		/* When outside hw range, reduce to fit (rounding errors) */
+		while ((un > 4095) || (um > 511)) {
+			un >>= 1;
+			um >>= 1;
+		}
+		if (un == 0)
+			un = 1;
+		if (um == 0)
+			um = 1;
+
+		*n = un;
+		*m = um;
+	}
+}
+
+static long cdce925_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *parent_rate)
+{
+	u16 n, m;
+
+	cdce925_pll_find_rate(rate, *parent_rate, &n, &m);
+	return (long)cdce925_pll_calculate_rate(*parent_rate, n, m);
+}
+
+static int cdce925_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
+
+	if (!rate || (rate == parent_rate)) {
+		data->m = 0; /* Bypass mode */
+		data->n = 0;
+		return 0;
+	}
+
+	if ((rate < CDCE925_PLL_FREQUENCY_MIN) ||
+		(rate > CDCE925_PLL_FREQUENCY_MAX)) {
+		pr_debug("%s: rate %lu outside PLL range.\n", __func__, rate);
+		return -EINVAL;
+	}
+
+	if (rate < parent_rate) {
+		pr_debug("%s: rate %lu less than parent rate %lu.\n", __func__,
+			rate, parent_rate);
+		return -EINVAL;
+	}
+
+	cdce925_pll_find_rate(rate, parent_rate, &data->n, &data->m);
+	return 0;
+}
+
+
+/* calculate p = max(0, 4 - int(log2 (n/m))) */
+static u8 cdce925_pll_calc_p(u16 n, u16 m)
+{
+	u8 p;
+	u16 r = n / m;
+
+	if (r >= 16)
+		return 0;
+	p = 4;
+	while (r > 1) {
+		r >>= 1;
+		--p;
+	}
+	return p;
+}
+
+/* Returns VCO range bits for VCO1_0_RANGE */
+static u8 cdce925_pll_calc_range_bits(struct clk_hw *hw, u16 n, u16 m)
+{
+	struct clk *parent = clk_get_parent(hw->clk);
+	unsigned long rate = clk_get_rate(parent);
+
+	rate = mult_frac(rate, (unsigned long)n, (unsigned long)m);
+	if (rate >= 175000000)
+		return 0x3;
+	if (rate >= 150000000)
+		return 0x02;
+	if (rate >= 125000000)
+		return 0x01;
+	return 0x00;
+}
+
+/* I2C clock, hence everything must happen in (un)prepare because this
+ * may sleep */
+static int cdce925_pll_prepare(struct clk_hw *hw)
+{
+	struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
+	u16 n = data->n;
+	u16 m = data->m;
+	u16 r;
+	u8 q;
+	u8 p;
+	u16 nn;
+	u8 pll[4]; /* Bits are spread out over 4 byte registers */
+	u8 reg_ofs = data->index * CDCE925_OFFSET_PLL;
+	unsigned i;
+
+	if ((!m || !n) || (m == n)) {
+		/* Set PLL mux to bypass mode, leave the rest as is */
+		regmap_update_bits(data->chip->regmap,
+			reg_ofs + CDCE925_PLL_MUX_OUTPUTS, 0x80, 0x80);
+	} else {
+		/* According to data sheet: */
+		/* p = max(0, 4 - int(log2 (n/m))) */
+		p = cdce925_pll_calc_p(n, m);
+		/* nn = n * 2^p */
+		nn = n * BIT(p);
+		/* q = int(nn/m) */
+		q = nn / m;
+		if ((q < 16) || (1 > 64)) {
+			pr_debug("%s invalid q=%d\n", __func__, q);
+			return -EINVAL;
+		}
+		r = nn - (m*q);
+		if (r > 511) {
+			pr_debug("%s invalid r=%d\n", __func__, r);
+			return -EINVAL;
+		}
+		pr_debug("%s n=%d m=%d p=%d q=%d r=%d\n", __func__,
+			n, m, p, q, r);
+		/* encode into register bits */
+		pll[0] = n >> 4;
+		pll[1] = ((n & 0x0F) << 4) | ((r >> 5) & 0x0F);
+		pll[2] = ((r & 0x1F) << 3) | ((q >> 3) & 0x07);
+		pll[3] = ((q & 0x07) << 5) | (p << 2) |
+				cdce925_pll_calc_range_bits(hw, n, m);
+		/* Write to registers */
+		for (i = 0; i < ARRAY_SIZE(pll); ++i)
+			regmap_write(data->chip->regmap,
+				reg_ofs + CDCE925_PLL_MULDIV + i, pll[i]);
+		/* Enable PLL */
+		regmap_update_bits(data->chip->regmap,
+			reg_ofs + CDCE925_PLL_MUX_OUTPUTS, 0x80, 0x00);
+	}
+
+	return 0;
+}
+
+static void cdce925_pll_unprepare(struct clk_hw *hw)
+{
+	struct clk_cdce925_pll *data = to_clk_cdce925_pll(hw);
+	u8 reg_ofs = data->index * CDCE925_OFFSET_PLL;
+
+	regmap_update_bits(data->chip->regmap,
+			reg_ofs + CDCE925_PLL_MUX_OUTPUTS, 0x80, 0x80);
+}
+
+static const struct clk_ops cdce925_pll_ops = {
+	.prepare = cdce925_pll_prepare,
+	.unprepare = cdce925_pll_unprepare,
+	.recalc_rate = cdce925_pll_recalc_rate,
+	.round_rate = cdce925_pll_round_rate,
+	.set_rate = cdce925_pll_set_rate,
+};
+
+
+static void cdce925_clk_set_pdiv(struct clk_cdce925_output *data, u16 pdiv)
+{
+	switch (data->index) {
+	case 0:
+		regmap_update_bits(data->chip->regmap,
+			CDCE925_REG_Y1SPIPDIVH,
+			0x03, (pdiv >> 8) & 0x03);
+		regmap_write(data->chip->regmap, 0x03, pdiv & 0xFF);
+		break;
+	case 1:
+		regmap_update_bits(data->chip->regmap, 0x16, 0x7F, pdiv);
+		break;
+	case 2:
+		regmap_update_bits(data->chip->regmap, 0x17, 0x7F, pdiv);
+		break;
+	case 3:
+		regmap_update_bits(data->chip->regmap, 0x26, 0x7F, pdiv);
+		break;
+	case 4:
+		regmap_update_bits(data->chip->regmap, 0x27, 0x7F, pdiv);
+		break;
+	}
+}
+
+static void cdce925_clk_activate(struct clk_cdce925_output *data)
+{
+	switch (data->index) {
+	case 0:
+		regmap_update_bits(data->chip->regmap,
+			CDCE925_REG_Y1SPIPDIVH, 0x0c, 0x0c);
+		break;
+	case 1:
+	case 2:
+		regmap_update_bits(data->chip->regmap, 0x14, 0x03, 0x03);
+		break;
+	case 3:
+	case 4:
+		regmap_update_bits(data->chip->regmap, 0x24, 0x03, 0x03);
+		break;
+	}
+}
+
+static int cdce925_clk_prepare(struct clk_hw *hw)
+{
+	struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+	cdce925_clk_set_pdiv(data, data->pdiv);
+	cdce925_clk_activate(data);
+	return 0;
+}
+
+static void cdce925_clk_unprepare(struct clk_hw *hw)
+{
+	struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+	/* Disable clock by setting divider to "0" */
+	cdce925_clk_set_pdiv(data, 0);
+}
+
+static unsigned long cdce925_clk_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+	if (data->pdiv)
+		return parent_rate / data->pdiv;
+	return 0;
+}
+
+static u16 cdce925_calc_divider(unsigned long rate,
+		unsigned long parent_rate)
+{
+	unsigned long divider;
+
+	if (!rate)
+		return 0;
+	if (rate >= parent_rate)
+		return 1;
+
+	divider = DIV_ROUND_CLOSEST(parent_rate, rate);
+	if (divider > 0x7F)
+		divider = 0x7F;
+
+	return (u16)divider;
+}
+
+static unsigned long cdce925_clk_best_parent_rate(
+	struct clk_hw *hw, unsigned long rate)
+{
+	struct clk *pll = clk_get_parent(hw->clk);
+	struct clk *root = clk_get_parent(pll);
+	unsigned long root_rate = clk_get_rate(root);
+	unsigned long best_rate_error = rate;
+	u16 pdiv_min;
+	u16 pdiv_max;
+	u16 pdiv_best;
+	u16 pdiv_now;
+
+	if (root_rate % rate == 0)
+		return root_rate; /* Don't need the PLL, use bypass */
+
+	pdiv_min = (u16)max(1ul, DIV_ROUND_UP(CDCE925_PLL_FREQUENCY_MIN, rate));
+	pdiv_max = (u16)min(127ul, CDCE925_PLL_FREQUENCY_MAX / rate);
+
+	if (pdiv_min > pdiv_max)
+		return 0; /* No can do? */
+
+	pdiv_best = pdiv_min;
+	for (pdiv_now = pdiv_min; pdiv_now < pdiv_max; ++pdiv_now) {
+		unsigned long target_rate = rate * pdiv_now;
+		long pll_rate = clk_round_rate(pll, target_rate);
+		unsigned long actual_rate;
+		unsigned long rate_error;
+
+		if (pll_rate <= 0)
+			continue;
+		actual_rate = pll_rate / pdiv_now;
+		rate_error = abs((long)actual_rate - (long)rate);
+		if (rate_error < best_rate_error) {
+			pdiv_best = pdiv_now;
+			best_rate_error = rate_error;
+		}
+		/* TODO: Consider PLL frequency based on smaller n/m values
+		 * and pick the better one if the error is equal */
+	}
+
+	return rate * pdiv_best;
+}
+
+static long cdce925_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *parent_rate)
+{
+	unsigned long l_parent_rate = *parent_rate;
+	u16 divider = cdce925_calc_divider(rate, l_parent_rate);
+
+	if (l_parent_rate / divider != rate) {
+		l_parent_rate = cdce925_clk_best_parent_rate(hw, rate);
+		divider = cdce925_calc_divider(rate, l_parent_rate);
+		*parent_rate = l_parent_rate;
+	}
+
+	if (divider)
+		return (long)(l_parent_rate / divider);
+	return 0;
+}
+
+static int cdce925_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+	data->pdiv = cdce925_calc_divider(rate, parent_rate);
+
+	return 0;
+}
+
+static const struct clk_ops cdce925_clk_ops = {
+	.prepare = cdce925_clk_prepare,
+	.unprepare = cdce925_clk_unprepare,
+	.recalc_rate = cdce925_clk_recalc_rate,
+	.round_rate = cdce925_clk_round_rate,
+	.set_rate = cdce925_clk_set_rate,
+};
+
+
+static u16 cdce925_y1_calc_divider(unsigned long rate,
+		unsigned long parent_rate)
+{
+	unsigned long divider;
+
+	if (!rate)
+		return 0;
+	if (rate >= parent_rate)
+		return 1;
+
+	divider = DIV_ROUND_CLOSEST(parent_rate, rate);
+	if (divider > 0x3FF) /* Y1 has 10-bit divider */
+		divider = 0x3FF;
+
+	return (u16)divider;
+}
+
+static long cdce925_clk_y1_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *parent_rate)
+{
+	unsigned long l_parent_rate = *parent_rate;
+	u16 divider = cdce925_y1_calc_divider(rate, l_parent_rate);
+
+	if (divider)
+		return (long)(l_parent_rate / divider);
+	return 0;
+}
+
+static int cdce925_clk_y1_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_cdce925_output *data = to_clk_cdce925_output(hw);
+
+	data->pdiv = cdce925_y1_calc_divider(rate, parent_rate);
+
+	return 0;
+}
+
+static const struct clk_ops cdce925_clk_y1_ops = {
+	.prepare = cdce925_clk_prepare,
+	.unprepare = cdce925_clk_unprepare,
+	.recalc_rate = cdce925_clk_recalc_rate,
+	.round_rate = cdce925_clk_y1_round_rate,
+	.set_rate = cdce925_clk_y1_set_rate,
+};
+
+
+static struct regmap_config cdce925_regmap_config = {
+	.name = "configuration0",
+	.reg_bits = 8,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.max_register = 0x2F,
+};
+
+#define CDCE925_I2C_COMMAND_BLOCK_TRANSFER	0x00
+#define CDCE925_I2C_COMMAND_BYTE_TRANSFER	0x80
+
+static int cdce925_regmap_i2c_write(
+	void *context, const void *data, size_t count)
+{
+	struct device *dev = context;
+	struct i2c_client *i2c = to_i2c_client(dev);
+	int ret;
+	u8 reg_data[2];
+
+	if (count != 2)
+		return -ENOTSUPP;
+
+	/* First byte is command code */
+	reg_data[0] = CDCE925_I2C_COMMAND_BYTE_TRANSFER | ((u8 *)data)[0];
+	reg_data[1] = ((u8 *)data)[1];
+
+	dev_dbg(&i2c->dev, "%s(%zu) %#x %#x\n", __func__, count,
+			reg_data[0], reg_data[1]);
+
+	ret = i2c_master_send(i2c, reg_data, count);
+	if (likely(ret == count))
+		return 0;
+	else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static int cdce925_regmap_i2c_read(void *context,
+	   const void *reg, size_t reg_size, void *val, size_t val_size)
+{
+	struct device *dev = context;
+	struct i2c_client *i2c = to_i2c_client(dev);
+	struct i2c_msg xfer[2];
+	int ret;
+	u8 reg_data[2];
+
+	if (reg_size != 1)
+		return -ENOTSUPP;
+
+	xfer[0].addr = i2c->addr;
+	xfer[0].flags = 0;
+	xfer[0].buf = reg_data;
+	if (val_size == 1) {
+		reg_data[0] =
+			CDCE925_I2C_COMMAND_BYTE_TRANSFER | ((u8 *)reg)[0];
+		xfer[0].len = 1;
+	} else {
+		reg_data[0] =
+			CDCE925_I2C_COMMAND_BLOCK_TRANSFER | ((u8 *)reg)[0];
+		reg_data[1] = val_size;
+		xfer[0].len = 2;
+	}
+
+	xfer[1].addr = i2c->addr;
+	xfer[1].flags = I2C_M_RD;
+	xfer[1].len = val_size;
+	xfer[1].buf = val;
+
+	ret = i2c_transfer(i2c->adapter, xfer, 2);
+	if (likely(ret == 2)) {
+		dev_dbg(&i2c->dev, "%s(%zu, %u) %#x %#x\n", __func__,
+				reg_size, val_size, reg_data[0], *((u8 *)val));
+		return 0;
+	} else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+/* The CDCE925 uses a funky way to read/write registers. Bulk mode is
+ * just weird, so just use the single byte mode exclusively. */
+static struct regmap_bus regmap_cdce925_bus = {
+	.write = cdce925_regmap_i2c_write,
+	.read = cdce925_regmap_i2c_read,
+};
+
+static int cdce925_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct clk_cdce925_chip *data;
+	struct device_node *node = client->dev.of_node;
+	const char *parent_name;
+	const char *pll_clk_name[NUMBER_OF_PLLS] = {NULL,};
+	struct clk_init_data init;
+	struct clk *clk;
+	u32 value;
+	int i;
+	int err;
+	struct device_node *np_output;
+	char child_name[6];
+
+	dev_dbg(&client->dev, "%s\n", __func__);
+	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->i2c_client = client;
+	data->regmap = devm_regmap_init(&client->dev, &regmap_cdce925_bus,
+			&client->dev, &cdce925_regmap_config);
+	if (IS_ERR(data->regmap)) {
+		dev_err(&client->dev, "failed to allocate register map\n");
+		return PTR_ERR(data->regmap);
+	}
+	i2c_set_clientdata(client, data);
+
+	parent_name = of_clk_get_parent_name(node, 0);
+	if (!parent_name) {
+		dev_err(&client->dev, "missing parent clock\n");
+		return -ENODEV;
+	}
+	dev_dbg(&client->dev, "parent is: %s\n", parent_name);
+
+	if (of_property_read_u32(node, "xtal-load-pf", &value) == 0)
+		regmap_write(data->regmap,
+			CDCE925_REG_XCSEL, (value << 3) & 0xF8);
+	/* PWDN bit */
+	regmap_update_bits(data->regmap, CDCE925_REG_GLOBAL1, BIT(4), 0);
+
+	/* Set input source for Y1 to be the XTAL */
+	regmap_update_bits(data->regmap, 0x02, BIT(7), 0);
+
+	init.ops = &cdce925_pll_ops;
+	init.flags = 0;
+	init.parent_names = &parent_name;
+	init.num_parents = parent_name ? 1 : 0;
+
+	/* Register PLL clocks */
+	for (i = 0; i < NUMBER_OF_PLLS; ++i) {
+		pll_clk_name[i] = kasprintf(GFP_KERNEL, "%s.pll%d",
+			client->dev.of_node->name, i);
+		init.name = pll_clk_name[i];
+		data->pll[i].chip = data;
+		data->pll[i].hw.init = &init;
+		data->pll[i].index = i;
+		clk = devm_clk_register(&client->dev, &data->pll[i].hw);
+		if (IS_ERR(clk)) {
+			dev_err(&client->dev, "Failed register PLL %d\n", i);
+			err = PTR_ERR(clk);
+			goto error;
+		}
+		sprintf(child_name, "PLL%d", i+1);
+		np_output = of_get_child_by_name(node, child_name);
+		if (!np_output)
+			continue;
+		if (!of_property_read_u32(np_output,
+			"clock-frequency", &value)) {
+			err = clk_set_rate(clk, value);
+			if (err)
+				dev_err(&client->dev,
+					"unable to set PLL frequency %ud\n",
+					value);
+		}
+		if (!of_property_read_u32(np_output,
+			"spread-spectrum", &value)) {
+			u8 flag = of_property_read_bool(np_output,
+				"spread-spectrum-center") ? 0x80 : 0x00;
+			regmap_update_bits(data->regmap,
+				0x16 + (i*CDCE925_OFFSET_PLL),
+				0x80, flag);
+			regmap_update_bits(data->regmap,
+				0x12 + (i*CDCE925_OFFSET_PLL),
+				0x07, value & 0x07);
+		}
+	}
+
+	/* Register output clock Y1 */
+	init.ops = &cdce925_clk_y1_ops;
+	init.flags = 0;
+	init.num_parents = 1;
+	init.parent_names = &parent_name; /* Mux Y1 to input */
+	init.name = kasprintf(GFP_KERNEL, "%s.Y1", client->dev.of_node->name);
+	data->clk[0].chip = data;
+	data->clk[0].hw.init = &init;
+	data->clk[0].index = 0;
+	data->clk[0].pdiv = 1;
+	clk = devm_clk_register(&client->dev, &data->clk[0].hw);
+	kfree(init.name); /* clock framework made a copy of the name */
+	if (IS_ERR(clk)) {
+		dev_err(&client->dev, "clock registration Y1 failed\n");
+		err = PTR_ERR(clk);
+		goto error;
+	}
+	data->dt_clk[0] = clk;
+
+	/* Register output clocks Y2 .. Y5*/
+	init.ops = &cdce925_clk_ops;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.num_parents = 1;
+	for (i = 1; i < NUMBER_OF_OUTPUTS; ++i) {
+		init.name = kasprintf(GFP_KERNEL, "%s.Y%d",
+			client->dev.of_node->name, i+1);
+		data->clk[i].chip = data;
+		data->clk[i].hw.init = &init;
+		data->clk[i].index = i;
+		data->clk[i].pdiv = 1;
+		switch (i) {
+		case 1:
+		case 2:
+			/* Mux Y2/3 to PLL1 */
+			init.parent_names = &pll_clk_name[0];
+			break;
+		case 3:
+		case 4:
+			/* Mux Y4/5 to PLL2 */
+			init.parent_names = &pll_clk_name[1];
+			break;
+		}
+		clk = devm_clk_register(&client->dev, &data->clk[i].hw);
+		kfree(init.name); /* clock framework made a copy of the name */
+		if (IS_ERR(clk)) {
+			dev_err(&client->dev, "clock registration failed\n");
+			err = PTR_ERR(clk);
+			goto error;
+		}
+		data->dt_clk[i] = clk;
+	}
+
+	/* Register the output clocks */
+	data->onecell.clk_num = NUMBER_OF_OUTPUTS;
+	data->onecell.clks = data->dt_clk;
+	err = of_clk_add_provider(client->dev.of_node, of_clk_src_onecell_get,
+		&data->onecell);
+	if (err)
+		dev_err(&client->dev, "unable to add OF clock provider\n");
+
+	err = 0;
+
+error:
+	for (i = 0; i < NUMBER_OF_PLLS; ++i)
+		/* clock framework made a copy of the name */
+		kfree(pll_clk_name[i]);
+
+	return err;
+}
+
+static const struct i2c_device_id cdce925_id[] = {
+	{ "cdce925", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, cdce925_id);
+
+static const struct of_device_id clk_cdce925_of_match[] = {
+	{ .compatible = "ti,cdce925" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, clk_cdce925_of_match);
+
+static struct i2c_driver cdce925_driver = {
+	.driver = {
+		.name = "cdce925",
+		.of_match_table = of_match_ptr(clk_cdce925_of_match),
+	},
+	.probe		= cdce925_probe,
+	.id_table	= cdce925_id,
+};
+module_i2c_driver(cdce925_driver);
+
+MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
+MODULE_DESCRIPTION("cdce925 driver");
+MODULE_LICENSE("GPL");

From a35247c6ee7265b024d606f7503fef44e88d9d2d Mon Sep 17 00:00:00 2001
From: Chao Xie <chao.xie@marvell.com>
Date: Thu, 30 Apr 2015 09:53:40 +0800
Subject: [PATCH 091/135] clk: mmp: add fixed clock UBS_PLL for pxa910/pxa168

USB will drive clock from USB_PLL.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/mmp/clk-of-pxa168.c            | 1 +
 drivers/clk/mmp/clk-of-pxa910.c            | 1 +
 include/dt-bindings/clock/marvell,pxa168.h | 1 +
 include/dt-bindings/clock/marvell,pxa910.h | 1 +
 4 files changed, 4 insertions(+)

diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c
index 5b1810dc4bd2..01a650e6f8a4 100644
--- a/drivers/clk/mmp/clk-of-pxa168.c
+++ b/drivers/clk/mmp/clk-of-pxa168.c
@@ -58,6 +58,7 @@ static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
 	{PXA168_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
 	{PXA168_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
 	{PXA168_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000},
+	{PXA168_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
 };
 
 static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c
index 5e3c80dad336..cca98eff641a 100644
--- a/drivers/clk/mmp/clk-of-pxa910.c
+++ b/drivers/clk/mmp/clk-of-pxa910.c
@@ -57,6 +57,7 @@ static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
 	{PXA910_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
 	{PXA910_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
 	{PXA910_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000},
+	{PXA910_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
 };
 
 static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
diff --git a/include/dt-bindings/clock/marvell,pxa168.h b/include/dt-bindings/clock/marvell,pxa168.h
index 79630b9d74b8..84ce5de6c83d 100644
--- a/include/dt-bindings/clock/marvell,pxa168.h
+++ b/include/dt-bindings/clock/marvell,pxa168.h
@@ -19,6 +19,7 @@
 #define PXA168_CLK_PLL1_2_1_5		19
 #define PXA168_CLK_PLL1_3_16		20
 #define PXA168_CLK_UART_PLL		27
+#define PXA168_CLK_USB_PLL		28
 
 /* apb periphrals */
 #define PXA168_CLK_TWSI0		60
diff --git a/include/dt-bindings/clock/marvell,pxa910.h b/include/dt-bindings/clock/marvell,pxa910.h
index 719cffb2bea2..bea08b60298b 100644
--- a/include/dt-bindings/clock/marvell,pxa910.h
+++ b/include/dt-bindings/clock/marvell,pxa910.h
@@ -19,6 +19,7 @@
 #define PXA910_CLK_PLL1_2_1_5		19
 #define PXA910_CLK_PLL1_3_16		20
 #define PXA910_CLK_UART_PLL		27
+#define PXA910_CLK_USB_PLL		28
 
 /* apb periphrals */
 #define PXA910_CLK_TWSI0		60

From 6644fddf062e1fa9bd56e74dfeaf864a14bf08cb Mon Sep 17 00:00:00 2001
From: Chao Xie <chao.xie@marvell.com>
Date: Thu, 30 Apr 2015 09:53:41 +0800
Subject: [PATCH 092/135] clk: mmp: Fix the wrong factor table for uart PLL

The suggested value in the mmp2 manual is wrong.
There are only 13 bits for numerator, but some suggested
value has 14 bits.
Fix the factor tabled and remove the unused items.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/mmp/clk-mmp2.c    | 4 +---
 drivers/clk/mmp/clk-of-mmp2.c | 4 +---
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
index 5c90a4230fa3..09d2832fbd78 100644
--- a/drivers/clk/mmp/clk-mmp2.c
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -63,10 +63,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
 };
 
 static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
-	{.num = 14634, .den = 2165},	/*14.745MHZ */
+	{.num = 8125, .den = 1536},	/*14.745MHZ */
 	{.num = 3521, .den = 689},	/*19.23MHZ */
-	{.num = 9679, .den = 5728},	/*58.9824MHZ */
-	{.num = 15850, .den = 9451},	/*59.429MHZ */
 };
 
 static const char *uart_parent[] = {"uart_pll", "vctcxo"};
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index 2cbc2b43ae52..b7e0b89b2e3f 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -98,10 +98,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
 };
 
 static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
-	{.num = 14634, .den = 2165},	/*14.745MHZ */
+	{.num = 8125, .den = 1536},	/*14.745MHZ */
 	{.num = 3521, .den = 689},	/*19.23MHZ */
-	{.num = 9679, .den = 5728},	/*58.9824MHZ */
-	{.num = 15850, .den = 9451},	/*59.429MHZ */
 };
 
 static void mmp2_pll_init(struct mmp2_clk_unit *pxa_unit)

From 24c65a02b23509284cce5185d81a150d699837b5 Mon Sep 17 00:00:00 2001
From: Chao Xie <chao.xie@marvell.com>
Date: Thu, 30 Apr 2015 09:53:42 +0800
Subject: [PATCH 093/135] clk: mmp: add timer clock for pxa168/mmp2/pxa910

Timer has external fast clock, and it is a mux clock.
Add the timer clock type for timer driver.

Signed-off-by: Chao Xie <chao.xie@marvell.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/mmp/clk-of-mmp2.c              |  6 ++++++
 drivers/clk/mmp/clk-of-pxa168.c            |  7 +++++++
 drivers/clk/mmp/clk-of-pxa910.c            | 11 +++++++++++
 include/dt-bindings/clock/marvell,mmp2.h   |  1 +
 include/dt-bindings/clock/marvell,pxa168.h |  2 ++
 include/dt-bindings/clock/marvell,pxa910.h |  3 +++
 6 files changed, 30 insertions(+)

diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index b7e0b89b2e3f..251533d87c65 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -30,6 +30,7 @@
 #define APBC_TWSI4	0x7c
 #define APBC_TWSI5	0x80
 #define APBC_KPC	0x18
+#define APBC_TIMER	0x24
 #define APBC_UART0	0x2c
 #define APBC_UART1	0x30
 #define APBC_UART2	0x34
@@ -132,6 +133,9 @@ static DEFINE_SPINLOCK(ssp2_lock);
 static DEFINE_SPINLOCK(ssp3_lock);
 static const char *ssp_parent_names[] = {"vctcxo_4", "vctcxo_2", "vctcxo", "pll1_16"};
 
+static DEFINE_SPINLOCK(timer_lock);
+static const char *timer_parent_names[] = {"clk32", "vctcxo_2", "vctcxo_4", "vctcxo"};
+
 static DEFINE_SPINLOCK(reset_lock);
 
 static struct mmp_param_mux_clk apbc_mux_clks[] = {
@@ -143,6 +147,7 @@ static struct mmp_param_mux_clk apbc_mux_clks[] = {
 	{0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock},
 	{0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock},
 	{0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock},
+	{0, "timer_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER, 4, 3, 0, &timer_lock},
 };
 
 static struct mmp_param_gate_clk apbc_gate_clks[] = {
@@ -168,6 +173,7 @@ static struct mmp_param_gate_clk apbc_gate_clks[] = {
 	{MMP2_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x7, 0x3, 0x0, 0, &ssp1_lock},
 	{MMP2_CLK_SSP2, "ssp2_clk", "ssp2_mux", CLK_SET_RATE_PARENT, APBC_SSP2, 0x7, 0x3, 0x0, 0, &ssp2_lock},
 	{MMP2_CLK_SSP3, "ssp3_clk", "ssp3_mux", CLK_SET_RATE_PARENT, APBC_SSP3, 0x7, 0x3, 0x0, 0, &ssp3_lock},
+	{MMP2_CLK_TIMER, "timer_clk", "timer_mux", CLK_SET_RATE_PARENT, APBC_TIMER, 0x7, 0x3, 0x0, 0, &timer_lock},
 };
 
 static void mmp2_apb_periph_clk_init(struct mmp2_clk_unit *pxa_unit)
diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c
index 01a650e6f8a4..64eaf4141c69 100644
--- a/drivers/clk/mmp/clk-of-pxa168.c
+++ b/drivers/clk/mmp/clk-of-pxa168.c
@@ -32,6 +32,7 @@
 #define APBC_PWM1	0x10
 #define APBC_PWM2	0x14
 #define APBC_PWM3	0x18
+#define APBC_TIMER	0x34
 #define APBC_SSP0	0x81c
 #define APBC_SSP1	0x820
 #define APBC_SSP2	0x84c
@@ -71,6 +72,7 @@ static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
 	{PXA168_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
 	{PXA168_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
 	{PXA168_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
+	{PXA168_CLK_PLL1_192, "pll1_192", "pll1_96", 1, 2, 0},
 	{PXA168_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
 	{PXA168_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
 	{PXA168_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
@@ -120,6 +122,9 @@ static DEFINE_SPINLOCK(ssp3_lock);
 static DEFINE_SPINLOCK(ssp4_lock);
 static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
 
+static DEFINE_SPINLOCK(timer_lock);
+static const char *timer_parent_names[] = {"pll1_48", "clk32", "pll1_96", "pll1_192"};
+
 static DEFINE_SPINLOCK(reset_lock);
 
 static struct mmp_param_mux_clk apbc_mux_clks[] = {
@@ -131,6 +136,7 @@ static struct mmp_param_mux_clk apbc_mux_clks[] = {
 	{0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock},
 	{0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock},
 	{0, "ssp4_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP4, 4, 3, 0, &ssp4_lock},
+	{0, "timer_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER, 4, 3, 0, &timer_lock},
 };
 
 static struct mmp_param_gate_clk apbc_gate_clks[] = {
@@ -152,6 +158,7 @@ static struct mmp_param_gate_clk apbc_gate_clks[] = {
 	{PXA168_CLK_SSP2, "ssp2_clk", "ssp2_mux", CLK_SET_RATE_PARENT, APBC_SSP2, 0x3, 0x3, 0x0, 0, &ssp2_lock},
 	{PXA168_CLK_SSP3, "ssp3_clk", "ssp3_mux", CLK_SET_RATE_PARENT, APBC_SSP3, 0x3, 0x3, 0x0, 0, &ssp3_lock},
 	{PXA168_CLK_SSP4, "ssp4_clk", "ssp4_mux", CLK_SET_RATE_PARENT, APBC_SSP4, 0x3, 0x3, 0x0, 0, &ssp4_lock},
+	{PXA168_CLK_TIMER, "timer_clk", "timer_mux", CLK_SET_RATE_PARENT, APBC_TIMER, 0x3, 0x3, 0x0, 0, &timer_lock},
 };
 
 static void pxa168_apb_periph_clk_init(struct pxa168_clk_unit *pxa_unit)
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c
index cca98eff641a..13d6173326a4 100644
--- a/drivers/clk/mmp/clk-of-pxa910.c
+++ b/drivers/clk/mmp/clk-of-pxa910.c
@@ -35,6 +35,8 @@
 #define APBC_SSP0	0x1c
 #define APBC_SSP1	0x20
 #define APBC_SSP2	0x4c
+#define APBC_TIMER0	0x30
+#define APBC_TIMER1	0x44
 #define APBCP_TWSI1	0x28
 #define APBCP_UART2	0x1c
 #define APMU_SDH0	0x54
@@ -70,6 +72,7 @@ static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
 	{PXA910_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
 	{PXA910_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
 	{PXA910_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
+	{PXA910_CLK_PLL1_192, "pll1_192", "pll1_96", 1, 2, 0},
 	{PXA910_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
 	{PXA910_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
 	{PXA910_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
@@ -116,6 +119,10 @@ static DEFINE_SPINLOCK(ssp0_lock);
 static DEFINE_SPINLOCK(ssp1_lock);
 static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
 
+static DEFINE_SPINLOCK(timer0_lock);
+static DEFINE_SPINLOCK(timer1_lock);
+static const char *timer_parent_names[] = {"pll1_48", "clk32", "pll1_96"};
+
 static DEFINE_SPINLOCK(reset_lock);
 
 static struct mmp_param_mux_clk apbc_mux_clks[] = {
@@ -123,6 +130,8 @@ static struct mmp_param_mux_clk apbc_mux_clks[] = {
 	{0, "uart1_mux", uart_parent_names, ARRAY_SIZE(uart_parent_names), CLK_SET_RATE_PARENT, APBC_UART1, 4, 3, 0, &uart1_lock},
 	{0, "ssp0_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP0, 4, 3, 0, &ssp0_lock},
 	{0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock},
+	{0, "timer0_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER0, 4, 3, 0, &timer0_lock},
+	{0, "timer1_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), CLK_SET_RATE_PARENT, APBC_TIMER1, 4, 3, 0, &timer1_lock},
 };
 
 static struct mmp_param_mux_clk apbcp_mux_clks[] = {
@@ -143,6 +152,8 @@ static struct mmp_param_gate_clk apbc_gate_clks[] = {
 	{PXA910_CLK_UART1, "uart1_clk", "uart1_mux", CLK_SET_RATE_PARENT, APBC_UART1, 0x3, 0x3, 0x0, 0, &uart1_lock},
 	{PXA910_CLK_SSP0, "ssp0_clk", "ssp0_mux", CLK_SET_RATE_PARENT, APBC_SSP0, 0x3, 0x3, 0x0, 0, &ssp0_lock},
 	{PXA910_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 0x3, 0x3, 0x0, 0, &ssp1_lock},
+	{PXA910_CLK_TIMER0, "timer0_clk", "timer0_mux", CLK_SET_RATE_PARENT, APBC_TIMER0, 0x3, 0x3, 0x0, 0, &timer0_lock},
+	{PXA910_CLK_TIMER1, "timer1_clk", "timer1_mux", CLK_SET_RATE_PARENT, APBC_TIMER1, 0x3, 0x3, 0x0, 0, &timer1_lock},
 };
 
 static struct mmp_param_gate_clk apbcp_gate_clks[] = {
diff --git a/include/dt-bindings/clock/marvell,mmp2.h b/include/dt-bindings/clock/marvell,mmp2.h
index 591f7fba89e2..7a510384a82a 100644
--- a/include/dt-bindings/clock/marvell,mmp2.h
+++ b/include/dt-bindings/clock/marvell,mmp2.h
@@ -48,6 +48,7 @@
 #define MMP2_CLK_SSP1			78
 #define MMP2_CLK_SSP2			79
 #define MMP2_CLK_SSP3			80
+#define MMP2_CLK_TIMER			81
 
 /* axi periphrals */
 #define MMP2_CLK_SDH0			101
diff --git a/include/dt-bindings/clock/marvell,pxa168.h b/include/dt-bindings/clock/marvell,pxa168.h
index 84ce5de6c83d..3e45bdfe1aa4 100644
--- a/include/dt-bindings/clock/marvell,pxa168.h
+++ b/include/dt-bindings/clock/marvell,pxa168.h
@@ -18,6 +18,7 @@
 #define PXA168_CLK_PLL1_13_1_5		18
 #define PXA168_CLK_PLL1_2_1_5		19
 #define PXA168_CLK_PLL1_3_16		20
+#define PXA168_CLK_PLL1_192		21
 #define PXA168_CLK_UART_PLL		27
 #define PXA168_CLK_USB_PLL		28
 
@@ -41,6 +42,7 @@
 #define PXA168_CLK_SSP2			76
 #define PXA168_CLK_SSP3			77
 #define PXA168_CLK_SSP4			78
+#define PXA168_CLK_TIMER		79
 
 /* axi periphrals */
 #define PXA168_CLK_DFC			100
diff --git a/include/dt-bindings/clock/marvell,pxa910.h b/include/dt-bindings/clock/marvell,pxa910.h
index bea08b60298b..135082a0b62f 100644
--- a/include/dt-bindings/clock/marvell,pxa910.h
+++ b/include/dt-bindings/clock/marvell,pxa910.h
@@ -18,6 +18,7 @@
 #define PXA910_CLK_PLL1_13_1_5		18
 #define PXA910_CLK_PLL1_2_1_5		19
 #define PXA910_CLK_PLL1_3_16		20
+#define PXA910_CLK_PLL1_192		21
 #define PXA910_CLK_UART_PLL		27
 #define PXA910_CLK_USB_PLL		28
 
@@ -38,6 +39,8 @@
 #define PXA910_CLK_UART2		73
 #define PXA910_CLK_SSP0			74
 #define PXA910_CLK_SSP1			75
+#define PXA910_CLK_TIMER0		76
+#define PXA910_CLK_TIMER1		77
 
 /* axi periphrals */
 #define PXA910_CLK_DFC			100

From 4f4adfbf8e655914bb80daa0252c90b62fd27d78 Mon Sep 17 00:00:00 2001
From: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
Date: Tue, 26 May 2015 19:01:07 -0300
Subject: [PATCH 094/135] clk: pistachio: Add a pll_lock() helper for clarity

This commit adds a pll_lock() helper making the code more readable.
Cosmetic change only, no functionality changes.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/pistachio/clk-pll.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/pistachio/clk-pll.c b/drivers/clk/pistachio/clk-pll.c
index de537560bf70..9ce1be779c9c 100644
--- a/drivers/clk/pistachio/clk-pll.c
+++ b/drivers/clk/pistachio/clk-pll.c
@@ -67,6 +67,12 @@ static inline void pll_writel(struct pistachio_clk_pll *pll, u32 val, u32 reg)
 	writel(val, pll->base + reg);
 }
 
+static inline void pll_lock(struct pistachio_clk_pll *pll)
+{
+	while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
+		cpu_relax();
+}
+
 static inline u32 do_div_round_closest(u64 dividend, u32 divisor)
 {
 	dividend += divisor / 2;
@@ -178,8 +184,7 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
 		(params->postdiv2 << PLL_FRAC_CTRL2_POSTDIV2_SHIFT);
 	pll_writel(pll, val, PLL_CTRL2);
 
-	while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
-		cpu_relax();
+	pll_lock(pll);
 
 	if (!was_enabled)
 		pll_gf40lp_frac_disable(hw);
@@ -288,8 +293,7 @@ static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
 		(params->postdiv2 << PLL_INT_CTRL1_POSTDIV2_SHIFT);
 	pll_writel(pll, val, PLL_CTRL1);
 
-	while (!(pll_readl(pll, PLL_STATUS) & PLL_STATUS_LOCK))
-		cpu_relax();
+	pll_lock(pll);
 
 	if (!was_enabled)
 		pll_gf40lp_laint_disable(hw);

From e0b7a79524771ad368abefbbcbd73f130f8e500e Mon Sep 17 00:00:00 2001
From: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
Date: Tue, 26 May 2015 19:01:08 -0300
Subject: [PATCH 095/135] clk: pistachio: Lock the PLL when enabled upon rate
 change

Currently, when the rate is changed, the driver makes sure the
PLL is enabled before doing so. This is done because the PLL
cannot be locked while disabled. Once locked, the drivers
returns the PLL to its previous enable/disable state.

This is a bit cumbersome, and can be simplified.

This commit reworks the .set_rate() functions for the integer
and fractional PLLs. Upon rate change, the PLL is now locked
only if it's already enabled.

Also, the driver locks the PLL on .enable(). This makes sure
the PLL is locked when enabled, and not locked when disabled.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/pistachio/clk-pll.c | 28 ++++++++++------------------
 1 file changed, 10 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/pistachio/clk-pll.c b/drivers/clk/pistachio/clk-pll.c
index 9ce1be779c9c..f12d5207e478 100644
--- a/drivers/clk/pistachio/clk-pll.c
+++ b/drivers/clk/pistachio/clk-pll.c
@@ -130,6 +130,8 @@ static int pll_gf40lp_frac_enable(struct clk_hw *hw)
 	val &= ~PLL_FRAC_CTRL4_BYPASS;
 	pll_writel(pll, val, PLL_CTRL4);
 
+	pll_lock(pll);
+
 	return 0;
 }
 
@@ -155,17 +157,13 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 	struct pistachio_pll_rate_table *params;
-	bool was_enabled;
+	int enabled = pll_gf40lp_frac_is_enabled(hw);
 	u32 val;
 
 	params = pll_get_params(pll, parent_rate, rate);
 	if (!params)
 		return -EINVAL;
 
-	was_enabled = pll_gf40lp_frac_is_enabled(hw);
-	if (!was_enabled)
-		pll_gf40lp_frac_enable(hw);
-
 	val = pll_readl(pll, PLL_CTRL1);
 	val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
 		 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT));
@@ -184,10 +182,8 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
 		(params->postdiv2 << PLL_FRAC_CTRL2_POSTDIV2_SHIFT);
 	pll_writel(pll, val, PLL_CTRL2);
 
-	pll_lock(pll);
-
-	if (!was_enabled)
-		pll_gf40lp_frac_disable(hw);
+	if (enabled)
+		pll_lock(pll);
 
 	return 0;
 }
@@ -246,6 +242,8 @@ static int pll_gf40lp_laint_enable(struct clk_hw *hw)
 	val &= ~PLL_INT_CTRL2_BYPASS;
 	pll_writel(pll, val, PLL_CTRL2);
 
+	pll_lock(pll);
+
 	return 0;
 }
 
@@ -271,17 +269,13 @@ static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 	struct pistachio_pll_rate_table *params;
-	bool was_enabled;
+	int enabled = pll_gf40lp_laint_is_enabled(hw);
 	u32 val;
 
 	params = pll_get_params(pll, parent_rate, rate);
 	if (!params)
 		return -EINVAL;
 
-	was_enabled = pll_gf40lp_laint_is_enabled(hw);
-	if (!was_enabled)
-		pll_gf40lp_laint_enable(hw);
-
 	val = pll_readl(pll, PLL_CTRL1);
 	val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
 		 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT) |
@@ -293,10 +287,8 @@ static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
 		(params->postdiv2 << PLL_INT_CTRL1_POSTDIV2_SHIFT);
 	pll_writel(pll, val, PLL_CTRL1);
 
-	pll_lock(pll);
-
-	if (!was_enabled)
-		pll_gf40lp_laint_disable(hw);
+	if (enabled)
+		pll_lock(pll);
 
 	return 0;
 }

From 17bfa3f7b3cd07e92b41ce7b5bea2dd8c8e2a8c3 Mon Sep 17 00:00:00 2001
From: Kevin Cernekee <cernekee@chromium.org>
Date: Tue, 26 May 2015 19:01:09 -0300
Subject: [PATCH 096/135] clk: pistachio: Add sanity checks on PLL
 configuration

When setting the PLL rates, check that:

 - VCO is within range
 - PFD is within range
 - PLL is disabled when postdiv is changed
 - postdiv2 <= postdiv1

Reviewed-by: Andrew Bresticker <abrestic@chromium.org>
Signed-off-by: Kevin Cernekee <cernekee@chromium.org>
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@imgtec.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/pistachio/clk-pll.c | 85 +++++++++++++++++++++++++++++++--
 1 file changed, 80 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/pistachio/clk-pll.c b/drivers/clk/pistachio/clk-pll.c
index f12d5207e478..e17dada0dd21 100644
--- a/drivers/clk/pistachio/clk-pll.c
+++ b/drivers/clk/pistachio/clk-pll.c
@@ -6,9 +6,12 @@
  * version 2, as published by the Free Software Foundation.
  */
 
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
+#include <linux/printk.h>
 #include <linux/slab.h>
 
 #include "clk.h"
@@ -50,6 +53,18 @@
 #define PLL_CTRL4			0x10
 #define PLL_FRAC_CTRL4_BYPASS		BIT(28)
 
+#define MIN_PFD				9600000UL
+#define MIN_VCO_LA			400000000UL
+#define MAX_VCO_LA			1600000000UL
+#define MIN_VCO_FRAC_INT		600000000UL
+#define MAX_VCO_FRAC_INT		1600000000UL
+#define MIN_VCO_FRAC_FRAC		600000000UL
+#define MAX_VCO_FRAC_FRAC		2400000000UL
+#define MIN_OUTPUT_LA			8000000UL
+#define MAX_OUTPUT_LA			1600000000UL
+#define MIN_OUTPUT_FRAC			12000000UL
+#define MAX_OUTPUT_FRAC			1600000000UL
+
 struct pistachio_clk_pll {
 	struct clk_hw hw;
 	void __iomem *base;
@@ -158,12 +173,29 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
 	struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 	struct pistachio_pll_rate_table *params;
 	int enabled = pll_gf40lp_frac_is_enabled(hw);
-	u32 val;
+	u32 val, vco, old_postdiv1, old_postdiv2;
+	const char *name = __clk_get_name(hw->clk);
+
+	if (rate < MIN_OUTPUT_FRAC || rate > MAX_OUTPUT_FRAC)
+		return -EINVAL;
 
 	params = pll_get_params(pll, parent_rate, rate);
-	if (!params)
+	if (!params || !params->refdiv)
 		return -EINVAL;
 
+	vco = params->fref * params->fbdiv / params->refdiv;
+	if (vco < MIN_VCO_FRAC_FRAC || vco > MAX_VCO_FRAC_FRAC)
+		pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
+			MIN_VCO_FRAC_FRAC, MAX_VCO_FRAC_FRAC);
+
+	val = params->fref / params->refdiv;
+	if (val < MIN_PFD)
+		pr_warn("%s: PFD %u is too low (min %lu)\n",
+			name, val, MIN_PFD);
+	if (val > vco / 16)
+		pr_warn("%s: PFD %u is too high (max %u)\n",
+			name, val, vco / 16);
+
 	val = pll_readl(pll, PLL_CTRL1);
 	val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
 		 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT));
@@ -172,6 +204,19 @@ static int pll_gf40lp_frac_set_rate(struct clk_hw *hw, unsigned long rate,
 	pll_writel(pll, val, PLL_CTRL1);
 
 	val = pll_readl(pll, PLL_CTRL2);
+
+	old_postdiv1 = (val >> PLL_FRAC_CTRL2_POSTDIV1_SHIFT) &
+		       PLL_FRAC_CTRL2_POSTDIV1_MASK;
+	old_postdiv2 = (val >> PLL_FRAC_CTRL2_POSTDIV2_SHIFT) &
+		       PLL_FRAC_CTRL2_POSTDIV2_MASK;
+	if (enabled &&
+	    (params->postdiv1 != old_postdiv1 ||
+	     params->postdiv2 != old_postdiv2))
+		pr_warn("%s: changing postdiv while PLL is enabled\n", name);
+
+	if (params->postdiv2 > params->postdiv1)
+		pr_warn("%s: postdiv2 should not exceed postdiv1\n", name);
+
 	val &= ~((PLL_FRAC_CTRL2_FRAC_MASK << PLL_FRAC_CTRL2_FRAC_SHIFT) |
 		 (PLL_FRAC_CTRL2_POSTDIV1_MASK <<
 		  PLL_FRAC_CTRL2_POSTDIV1_SHIFT) |
@@ -270,13 +315,43 @@ static int pll_gf40lp_laint_set_rate(struct clk_hw *hw, unsigned long rate,
 	struct pistachio_clk_pll *pll = to_pistachio_pll(hw);
 	struct pistachio_pll_rate_table *params;
 	int enabled = pll_gf40lp_laint_is_enabled(hw);
-	u32 val;
+	u32 val, vco, old_postdiv1, old_postdiv2;
+	const char *name = __clk_get_name(hw->clk);
 
-	params = pll_get_params(pll, parent_rate, rate);
-	if (!params)
+	if (rate < MIN_OUTPUT_LA || rate > MAX_OUTPUT_LA)
 		return -EINVAL;
 
+	params = pll_get_params(pll, parent_rate, rate);
+	if (!params || !params->refdiv)
+		return -EINVAL;
+
+	vco = params->fref * params->fbdiv / params->refdiv;
+	if (vco < MIN_VCO_LA || vco > MAX_VCO_LA)
+		pr_warn("%s: VCO %u is out of range %lu..%lu\n", name, vco,
+			MIN_VCO_LA, MAX_VCO_LA);
+
+	val = params->fref / params->refdiv;
+	if (val < MIN_PFD)
+		pr_warn("%s: PFD %u is too low (min %lu)\n",
+			name, val, MIN_PFD);
+	if (val > vco / 16)
+		pr_warn("%s: PFD %u is too high (max %u)\n",
+			name, val, vco / 16);
+
 	val = pll_readl(pll, PLL_CTRL1);
+
+	old_postdiv1 = (val >> PLL_INT_CTRL1_POSTDIV1_SHIFT) &
+		       PLL_INT_CTRL1_POSTDIV1_MASK;
+	old_postdiv2 = (val >> PLL_INT_CTRL1_POSTDIV2_SHIFT) &
+		       PLL_INT_CTRL1_POSTDIV2_MASK;
+	if (enabled &&
+	    (params->postdiv1 != old_postdiv1 ||
+	     params->postdiv2 != old_postdiv2))
+		pr_warn("%s: changing postdiv while PLL is enabled\n", name);
+
+	if (params->postdiv2 > params->postdiv1)
+		pr_warn("%s: postdiv2 should not exceed postdiv1\n", name);
+
 	val &= ~((PLL_CTRL1_REFDIV_MASK << PLL_CTRL1_REFDIV_SHIFT) |
 		 (PLL_CTRL1_FBDIV_MASK << PLL_CTRL1_FBDIV_SHIFT) |
 		 (PLL_INT_CTRL1_POSTDIV1_MASK << PLL_INT_CTRL1_POSTDIV1_SHIFT) |

From 51a43be9fa9016e02ef9c4214470c919223d138c Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas@glider.be>
Date: Fri, 29 May 2015 11:25:45 +0200
Subject: [PATCH 097/135] clk: at91: Use of_clk_get_parent_count() instead of
 open coding

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/at91/clk-main.c         | 2 +-
 drivers/clk/at91/clk-master.c       | 2 +-
 drivers/clk/at91/clk-programmable.c | 2 +-
 drivers/clk/at91/clk-slow.c         | 4 ++--
 drivers/clk/at91/clk-smd.c          | 2 +-
 drivers/clk/at91/clk-usb.c          | 2 +-
 6 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c
index 59fa3cc96c9e..c2400456a044 100644
--- a/drivers/clk/at91/clk-main.c
+++ b/drivers/clk/at91/clk-main.c
@@ -614,7 +614,7 @@ void __init of_at91sam9x5_clk_main_setup(struct device_node *np,
 	const char *name = np->name;
 	int i;
 
-	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	num_parents = of_clk_get_parent_count(np);
 	if (num_parents <= 0 || num_parents > 2)
 		return;
 
diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
index c1af80bcdf20..f98eafe9b12d 100644
--- a/drivers/clk/at91/clk-master.c
+++ b/drivers/clk/at91/clk-master.c
@@ -224,7 +224,7 @@ of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc,
 	const char *name = np->name;
 	struct clk_master_characteristics *characteristics;
 
-	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	num_parents = of_clk_get_parent_count(np);
 	if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX)
 		return;
 
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
index 86c8a073dcc3..8c86c0f7847a 100644
--- a/drivers/clk/at91/clk-programmable.c
+++ b/drivers/clk/at91/clk-programmable.c
@@ -237,7 +237,7 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc,
 	const char *name;
 	struct device_node *progclknp;
 
-	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	num_parents = of_clk_get_parent_count(np);
 	if (num_parents <= 0 || num_parents > PROG_SOURCE_MAX)
 		return;
 
diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c
index 2f13bd5246b5..98a84a865fe1 100644
--- a/drivers/clk/at91/clk-slow.c
+++ b/drivers/clk/at91/clk-slow.c
@@ -373,7 +373,7 @@ void __init of_at91sam9x5_clk_slow_setup(struct device_node *np,
 	const char *name = np->name;
 	int i;
 
-	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	num_parents = of_clk_get_parent_count(np);
 	if (num_parents <= 0 || num_parents > 2)
 		return;
 
@@ -451,7 +451,7 @@ void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
 	const char *name = np->name;
 	int i;
 
-	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	num_parents = of_clk_get_parent_count(np);
 	if (num_parents != 2)
 		return;
 
diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c
index 144d47ecfe63..3817ea865ca2 100644
--- a/drivers/clk/at91/clk-smd.c
+++ b/drivers/clk/at91/clk-smd.c
@@ -150,7 +150,7 @@ void __init of_at91sam9x5_clk_smd_setup(struct device_node *np,
 	const char *parent_names[SMD_SOURCE_MAX];
 	const char *name = np->name;
 
-	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	num_parents = of_clk_get_parent_count(np);
 	if (num_parents <= 0 || num_parents > SMD_SOURCE_MAX)
 		return;
 
diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c
index 0b7c3e8840ba..b0cbd2b1ff59 100644
--- a/drivers/clk/at91/clk-usb.c
+++ b/drivers/clk/at91/clk-usb.c
@@ -378,7 +378,7 @@ void __init of_at91sam9x5_clk_usb_setup(struct device_node *np,
 	const char *parent_names[USB_SOURCE_MAX];
 	const char *name = np->name;
 
-	num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	num_parents = of_clk_get_parent_count(np);
 	if (num_parents <= 0 || num_parents > USB_SOURCE_MAX)
 		return;
 

From 0a65239c280bb0d56d8d84c4a9cc78bc68144925 Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas@glider.be>
Date: Fri, 29 May 2015 11:25:46 +0200
Subject: [PATCH 098/135] clk: st: Use of_clk_get_parent_count() instead of
 open coding

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/st/clk-flexgen.c | 2 +-
 drivers/clk/st/clkgen-mux.c  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index 409ed4b0b569..657ca14ba709 100644
--- a/drivers/clk/st/clk-flexgen.c
+++ b/drivers/clk/st/clk-flexgen.c
@@ -245,7 +245,7 @@ static const char ** __init flexgen_get_parents(struct device_node *np,
 	const char **parents;
 	int nparents, i;
 
-	nparents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	nparents = of_clk_get_parent_count(np);
 	if (WARN_ON(nparents <= 0))
 		return NULL;
 
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index 80aa77dbf660..4fbe6e099587 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -26,7 +26,7 @@ static const char ** __init clkgen_mux_get_parents(struct device_node *np,
 	const char **parents;
 	int nparents, i;
 
-	nparents = of_count_phandle_with_args(np, "clocks", "#clock-cells");
+	nparents = of_clk_get_parent_count(np);
 	if (WARN_ON(nparents <= 0))
 		return ERR_PTR(-EINVAL);
 

From f71355b3d14421784f13c44b66fe0fbc7d3dbdb1 Mon Sep 17 00:00:00 2001
From: Geert Uytterhoeven <geert+renesas@glider.be>
Date: Fri, 29 May 2015 11:25:47 +0200
Subject: [PATCH 099/135] clk: ti: Use of_clk_get_parent_count() instead of
 open coding

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/ti/clockdomain.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c
index 35fe1085480c..b82ef07f3403 100644
--- a/drivers/clk/ti/clockdomain.c
+++ b/drivers/clk/ti/clockdomain.c
@@ -32,7 +32,7 @@ static void __init of_ti_clockdomain_setup(struct device_node *node)
 	int i;
 	int num_clks;
 
-	num_clks = of_count_phandle_with_args(node, "clocks", "#clock-cells");
+	num_clks = of_clk_get_parent_count(node);
 
 	for (i = 0; i < num_clks; i++) {
 		clk = of_clk_get(node, i);

From 90acb40f1874f7b304b1d8d9b07c72aa83337e31 Mon Sep 17 00:00:00 2001
From: James Liao <jamesjj.liao@mediatek.com>
Date: Thu, 21 May 2015 15:12:52 +0800
Subject: [PATCH 100/135] clk: mediatek: Fix apmixedsys clock registration

The size of clk_data should be the same as CLK_APMIXED_NR_CLK
instead of ARRAY_SIZE(plls). CLK_APMIXED_* is numbered from 1, so
CLK_APMIXED_NR_CLK will be greater than ARRAY_SIZE(plls).

Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/mediatek/clk-mt8135.c | 2 +-
 drivers/clk/mediatek/clk-mt8173.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c
index a63435b95822..08b4b849b491 100644
--- a/drivers/clk/mediatek/clk-mt8135.c
+++ b/drivers/clk/mediatek/clk-mt8135.c
@@ -634,7 +634,7 @@ static void __init mtk_apmixedsys_init(struct device_node *node)
 {
 	struct clk_onecell_data *clk_data;
 
-	clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
+	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
 	if (!clk_data)
 		return;
 
diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
index 357b080eb04f..4b9e04cdf7e8 100644
--- a/drivers/clk/mediatek/clk-mt8173.c
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -818,7 +818,7 @@ static void __init mtk_apmixedsys_init(struct device_node *node)
 {
 	struct clk_onecell_data *clk_data;
 
-	clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
+	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
 	if (!clk_data)
 		return;
 

From 4a1caed3d0c2fbf8c9f18909bec69e2aa2638b97 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
Date: Thu, 28 May 2015 10:45:51 +0200
Subject: [PATCH 101/135] clk: make several parent names const
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Since commit 2893c379461a ("clk: make strings in parent name arrays
const") the name of parent clocks can be const. So add more const in
several clock drivers.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Acked-by: Heiko Stuebner <heiko@sntech.de>
Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/hisilicon/clk-hi3620.c   | 70 +++++++++++-----------
 drivers/clk/hisilicon/clk-hix5hd2.c  |  6 +-
 drivers/clk/hisilicon/clk.h          |  2 +-
 drivers/clk/mxs/clk-imx23.c          | 12 ++--
 drivers/clk/mxs/clk-imx28.c          | 18 +++---
 drivers/clk/mxs/clk.h                |  2 +-
 drivers/clk/pxa/clk-pxa.h            |  2 +-
 drivers/clk/rockchip/clk-cpu.c       |  2 +-
 drivers/clk/rockchip/clk-mmc-phase.c |  2 +-
 drivers/clk/rockchip/clk-pll.c       |  8 +--
 drivers/clk/rockchip/clk.c           |  8 +--
 drivers/clk/rockchip/clk.h           | 20 +++----
 drivers/clk/samsung/clk-pll.c        |  4 +-
 drivers/clk/samsung/clk-s5pv210.c    | 88 ++++++++++++++--------------
 drivers/clk/samsung/clk.c            | 13 ++--
 drivers/clk/samsung/clk.h            | 18 +++---
 drivers/clk/zynq/clkc.c              | 25 +++++---
 17 files changed, 154 insertions(+), 146 deletions(-)

diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index 472dd2cb10b3..715d34a5ef9b 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -38,44 +38,44 @@
 #include "clk.h"
 
 /* clock parent list */
-static const char *timer0_mux_p[] __initdata = { "osc32k", "timerclk01", };
-static const char *timer1_mux_p[] __initdata = { "osc32k", "timerclk01", };
-static const char *timer2_mux_p[] __initdata = { "osc32k", "timerclk23", };
-static const char *timer3_mux_p[] __initdata = { "osc32k", "timerclk23", };
-static const char *timer4_mux_p[] __initdata = { "osc32k", "timerclk45", };
-static const char *timer5_mux_p[] __initdata = { "osc32k", "timerclk45", };
-static const char *timer6_mux_p[] __initdata = { "osc32k", "timerclk67", };
-static const char *timer7_mux_p[] __initdata = { "osc32k", "timerclk67", };
-static const char *timer8_mux_p[] __initdata = { "osc32k", "timerclk89", };
-static const char *timer9_mux_p[] __initdata = { "osc32k", "timerclk89", };
-static const char *uart0_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *uart1_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *uart2_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *uart3_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *uart4_mux_p[] __initdata = { "osc26m", "pclk", };
-static const char *spi0_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
-static const char *spi1_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
-static const char *spi2_mux_p[] __initdata = { "osc26m", "rclk_cfgaxi", };
+static const char *const timer0_mux_p[] __initconst = { "osc32k", "timerclk01", };
+static const char *const timer1_mux_p[] __initconst = { "osc32k", "timerclk01", };
+static const char *const timer2_mux_p[] __initconst = { "osc32k", "timerclk23", };
+static const char *const timer3_mux_p[] __initconst = { "osc32k", "timerclk23", };
+static const char *const timer4_mux_p[] __initconst = { "osc32k", "timerclk45", };
+static const char *const timer5_mux_p[] __initconst = { "osc32k", "timerclk45", };
+static const char *const timer6_mux_p[] __initconst = { "osc32k", "timerclk67", };
+static const char *const timer7_mux_p[] __initconst = { "osc32k", "timerclk67", };
+static const char *const timer8_mux_p[] __initconst = { "osc32k", "timerclk89", };
+static const char *const timer9_mux_p[] __initconst = { "osc32k", "timerclk89", };
+static const char *const uart0_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const uart1_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const uart2_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const uart3_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const uart4_mux_p[] __initconst = { "osc26m", "pclk", };
+static const char *const spi0_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
+static const char *const spi1_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
+static const char *const spi2_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
 /* share axi parent */
-static const char *saxi_mux_p[] __initdata = { "armpll3", "armpll2", };
-static const char *pwm0_mux_p[] __initdata = { "osc32k", "osc26m", };
-static const char *pwm1_mux_p[] __initdata = { "osc32k", "osc26m", };
-static const char *sd_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *mmc1_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *mmc1_mux2_p[] __initdata = { "osc26m", "mmc1_div", };
-static const char *g2d_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *venc_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *vdec_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *vpp_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *edc0_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *ldi0_mux_p[] __initdata = { "armpll2", "armpll4",
+static const char *const saxi_mux_p[] __initconst = { "armpll3", "armpll2", };
+static const char *const pwm0_mux_p[] __initconst = { "osc32k", "osc26m", };
+static const char *const pwm1_mux_p[] __initconst = { "osc32k", "osc26m", };
+static const char *const sd_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const mmc1_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const mmc1_mux2_p[] __initconst = { "osc26m", "mmc1_div", };
+static const char *const g2d_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const venc_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const vdec_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const vpp_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const edc0_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const ldi0_mux_p[] __initconst = { "armpll2", "armpll4",
 					     "armpll3", "armpll5", };
-static const char *edc1_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *ldi1_mux_p[] __initdata = { "armpll2", "armpll4",
+static const char *const edc1_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const ldi1_mux_p[] __initconst = { "armpll2", "armpll4",
 					     "armpll3", "armpll5", };
-static const char *rclk_hsic_p[] __initdata = { "armpll3", "armpll2", };
-static const char *mmc2_mux_p[] __initdata = { "armpll2", "armpll3", };
-static const char *mmc3_mux_p[] __initdata = { "armpll2", "armpll3", };
+static const char *const rclk_hsic_p[] __initconst = { "armpll3", "armpll2", };
+static const char *const mmc2_mux_p[] __initconst = { "armpll2", "armpll3", };
+static const char *const mmc3_mux_p[] __initconst = { "armpll2", "armpll3", };
 
 
 /* fixed rate clocks */
diff --git a/drivers/clk/hisilicon/clk-hix5hd2.c b/drivers/clk/hisilicon/clk-hix5hd2.c
index 78bd95b6fc7b..0aaf29da8491 100644
--- a/drivers/clk/hisilicon/clk-hix5hd2.c
+++ b/drivers/clk/hisilicon/clk-hix5hd2.c
@@ -46,15 +46,15 @@ static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] __initdata = {
 	{ HIX5HD2_FIXED_83M, "83m", NULL, CLK_IS_ROOT, 83333333, },
 };
 
-static const char *sfc_mux_p[] __initdata = {
+static const char *const sfc_mux_p[] __initconst = {
 		"24m", "150m", "200m", "100m", "75m", };
 static u32 sfc_mux_table[] = {0, 4, 5, 6, 7};
 
-static const char *sdio_mux_p[] __initdata = {
+static const char *const sdio_mux_p[] __initconst = {
 		"75m", "100m", "50m", "15m", };
 static u32 sdio_mux_table[] = {0, 1, 2, 3};
 
-static const char *fephy_mux_p[] __initdata = { "25m", "125m"};
+static const char *const fephy_mux_p[] __initconst = { "25m", "125m"};
 static u32 fephy_mux_table[] = {0, 1};
 
 
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index 21b403b3423a..b56fbc1c5f27 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -55,7 +55,7 @@ struct hisi_fixed_factor_clock {
 struct hisi_mux_clock {
 	unsigned int		id;
 	const char		*name;
-	const char		**parent_names;
+	const char		*const *parent_names;
 	u8			num_parents;
 	unsigned long		flags;
 	unsigned long		offset;
diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c
index 22d136aa699f..32216f9b7f03 100644
--- a/drivers/clk/mxs/clk-imx23.c
+++ b/drivers/clk/mxs/clk-imx23.c
@@ -77,12 +77,12 @@ static void __init clk_misc_init(void)
 	writel_relaxed(30 << BP_FRAC_IOFRAC, FRAC + SET);
 }
 
-static const char *sel_pll[]  __initdata = { "pll", "ref_xtal", };
-static const char *sel_cpu[]  __initdata = { "ref_cpu", "ref_xtal", };
-static const char *sel_pix[]  __initdata = { "ref_pix", "ref_xtal", };
-static const char *sel_io[]   __initdata = { "ref_io", "ref_xtal", };
-static const char *cpu_sels[] __initdata = { "cpu_pll", "cpu_xtal", };
-static const char *emi_sels[] __initdata = { "emi_pll", "emi_xtal", };
+static const char *const sel_pll[]  __initconst = { "pll", "ref_xtal", };
+static const char *const sel_cpu[]  __initconst = { "ref_cpu", "ref_xtal", };
+static const char *const sel_pix[]  __initconst = { "ref_pix", "ref_xtal", };
+static const char *const sel_io[]   __initconst = { "ref_io", "ref_xtal", };
+static const char *const cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", };
+static const char *const emi_sels[] __initconst = { "emi_pll", "emi_xtal", };
 
 enum imx23_clk {
 	ref_xtal, pll, ref_cpu, ref_emi, ref_pix, ref_io, saif_sel,
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index b1be3746ce95..a68670868baa 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -125,15 +125,15 @@ static void __init clk_misc_init(void)
 	writel_relaxed(val, FRAC0);
 }
 
-static const char *sel_cpu[]  __initdata = { "ref_cpu", "ref_xtal", };
-static const char *sel_io0[]  __initdata = { "ref_io0", "ref_xtal", };
-static const char *sel_io1[]  __initdata = { "ref_io1", "ref_xtal", };
-static const char *sel_pix[]  __initdata = { "ref_pix", "ref_xtal", };
-static const char *sel_gpmi[] __initdata = { "ref_gpmi", "ref_xtal", };
-static const char *sel_pll0[] __initdata = { "pll0", "ref_xtal", };
-static const char *cpu_sels[] __initdata = { "cpu_pll", "cpu_xtal", };
-static const char *emi_sels[] __initdata = { "emi_pll", "emi_xtal", };
-static const char *ptp_sels[] __initdata = { "ref_xtal", "pll0", };
+static const char *const sel_cpu[]  __initconst = { "ref_cpu", "ref_xtal", };
+static const char *const sel_io0[]  __initconst = { "ref_io0", "ref_xtal", };
+static const char *const sel_io1[]  __initconst = { "ref_io1", "ref_xtal", };
+static const char *const sel_pix[]  __initconst = { "ref_pix", "ref_xtal", };
+static const char *const sel_gpmi[] __initconst = { "ref_gpmi", "ref_xtal", };
+static const char *const sel_pll0[] __initconst = { "pll0", "ref_xtal", };
+static const char *const cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", };
+static const char *const emi_sels[] __initconst = { "emi_pll", "emi_xtal", };
+static const char *const ptp_sels[] __initconst = { "ref_xtal", "pll0", };
 
 enum imx28_clk {
 	ref_xtal, pll0, pll1, pll2, ref_cpu, ref_emi, ref_io0, ref_io1,
diff --git a/drivers/clk/mxs/clk.h b/drivers/clk/mxs/clk.h
index ef10ad9b5daa..f07d821dd75d 100644
--- a/drivers/clk/mxs/clk.h
+++ b/drivers/clk/mxs/clk.h
@@ -49,7 +49,7 @@ static inline struct clk *mxs_clk_gate(const char *name,
 }
 
 static inline struct clk *mxs_clk_mux(const char *name, void __iomem *reg,
-		u8 shift, u8 width, const char **parent_names, int num_parents)
+		u8 shift, u8 width, const char *const *parent_names, int num_parents)
 {
 	return clk_register_mux(NULL, name, parent_names, num_parents,
 				CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
diff --git a/drivers/clk/pxa/clk-pxa.h b/drivers/clk/pxa/clk-pxa.h
index b04c5b9c0ea8..7bf532dca709 100644
--- a/drivers/clk/pxa/clk-pxa.h
+++ b/drivers/clk/pxa/clk-pxa.h
@@ -14,7 +14,7 @@
 #define _CLK_PXA_
 
 #define PARENTS(name) \
-	static const char *name ## _parents[] __initdata
+	static const char *const name ## _parents[] __initconst
 #define MUX_RO_RATE_RO_OPS(name, clk_name)			\
 	static struct clk_hw name ## _mux_hw;			\
 	static struct clk_hw name ## _rate_hw;			\
diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c
index 8539c4fd34cc..fb7721bd37e6 100644
--- a/drivers/clk/rockchip/clk-cpu.c
+++ b/drivers/clk/rockchip/clk-cpu.c
@@ -231,7 +231,7 @@ static int rockchip_cpuclk_notifier_cb(struct notifier_block *nb,
 }
 
 struct clk *rockchip_clk_register_cpuclk(const char *name,
-			const char **parent_names, u8 num_parents,
+			const char *const *parent_names, u8 num_parents,
 			const struct rockchip_cpuclk_reg_data *reg_data,
 			const struct rockchip_cpuclk_rate_table *rates,
 			int nrates, void __iomem *reg_base, spinlock_t *lock)
diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
index c842e3b60f21..e9f8df324e7c 100644
--- a/drivers/clk/rockchip/clk-mmc-phase.c
+++ b/drivers/clk/rockchip/clk-mmc-phase.c
@@ -120,7 +120,7 @@ static const struct clk_ops rockchip_mmc_clk_ops = {
 };
 
 struct clk *rockchip_clk_register_mmc(const char *name,
-				const char **parent_names, u8 num_parents,
+				const char *const *parent_names, u8 num_parents,
 				void __iomem *reg, int shift)
 {
 	struct clk_init_data init;
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index f8d3baf275b2..76027261f7ed 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -329,10 +329,10 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = {
  */
 
 struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
-		const char *name, const char **parent_names, u8 num_parents,
-		void __iomem *base, int con_offset, int grf_lock_offset,
-		int lock_shift, int mode_offset, int mode_shift,
-		struct rockchip_pll_rate_table *rate_table,
+		const char *name, const char *const *parent_names,
+		u8 num_parents, void __iomem *base, int con_offset,
+		int grf_lock_offset, int lock_shift, int mode_offset,
+		int mode_shift, struct rockchip_pll_rate_table *rate_table,
 		u8 clk_pll_flags, spinlock_t *lock)
 {
 	const char *pll_parents[3];
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index edb5d489ae61..052b94db0ff9 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -39,7 +39,7 @@
  * sometimes without one of those components.
  */
 static struct clk *rockchip_clk_register_branch(const char *name,
-		const char **parent_names, u8 num_parents, void __iomem *base,
+		const char *const *parent_names, u8 num_parents, void __iomem *base,
 		int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
 		u8 div_shift, u8 div_width, u8 div_flags,
 		struct clk_div_table *div_table, int gate_offset,
@@ -103,8 +103,8 @@ static struct clk *rockchip_clk_register_branch(const char *name,
 }
 
 static struct clk *rockchip_clk_register_frac_branch(const char *name,
-		const char **parent_names, u8 num_parents, void __iomem *base,
-		int muxdiv_offset, u8 div_flags,
+		const char *const *parent_names, u8 num_parents,
+		void __iomem *base, int muxdiv_offset, u8 div_flags,
 		int gate_offset, u8 gate_shift, u8 gate_flags,
 		unsigned long flags, spinlock_t *lock)
 {
@@ -297,7 +297,7 @@ void __init rockchip_clk_register_branches(
 }
 
 void __init rockchip_clk_register_armclk(unsigned int lookup_id,
-			const char *name, const char **parent_names,
+			const char *name, const char *const *parent_names,
 			u8 num_parents,
 			const struct rockchip_cpuclk_reg_data *reg_data,
 			const struct rockchip_cpuclk_rate_table *rates,
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index e63cafe893e1..6b092673048a 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -108,7 +108,7 @@ struct rockchip_pll_rate_table {
 struct rockchip_pll_clock {
 	unsigned int		id;
 	const char		*name;
-	const char		**parent_names;
+	const char		*const *parent_names;
 	u8			num_parents;
 	unsigned long		flags;
 	int			con_offset;
@@ -140,10 +140,10 @@ struct rockchip_pll_clock {
 	}
 
 struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
-		const char *name, const char **parent_names, u8 num_parents,
-		void __iomem *base, int con_offset, int grf_lock_offset,
-		int lock_shift, int reg_mode, int mode_shift,
-		struct rockchip_pll_rate_table *rate_table,
+		const char *name, const char *const *parent_names,
+		u8 num_parents, void __iomem *base, int con_offset,
+		int grf_lock_offset, int lock_shift, int reg_mode,
+		int mode_shift, struct rockchip_pll_rate_table *rate_table,
 		u8 clk_pll_flags, spinlock_t *lock);
 
 struct rockchip_cpuclk_clksel {
@@ -173,16 +173,16 @@ struct rockchip_cpuclk_reg_data {
 };
 
 struct clk *rockchip_clk_register_cpuclk(const char *name,
-			const char **parent_names, u8 num_parents,
+			const char *const *parent_names, u8 num_parents,
 			const struct rockchip_cpuclk_reg_data *reg_data,
 			const struct rockchip_cpuclk_rate_table *rates,
 			int nrates, void __iomem *reg_base, spinlock_t *lock);
 
 struct clk *rockchip_clk_register_mmc(const char *name,
-				const char **parent_names, u8 num_parents,
+				const char *const *parent_names, u8 num_parents,
 				void __iomem *reg, int shift);
 
-#define PNAME(x) static const char *x[] __initdata
+#define PNAME(x) static const char *const x[] __initconst
 
 enum rockchip_clk_branch_type {
 	branch_composite,
@@ -197,7 +197,7 @@ struct rockchip_clk_branch {
 	unsigned int			id;
 	enum rockchip_clk_branch_type	branch_type;
 	const char			*name;
-	const char			**parent_names;
+	const char			*const *parent_names;
 	u8				num_parents;
 	unsigned long			flags;
 	int				muxdiv_offset;
@@ -403,7 +403,7 @@ void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
 void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
 				unsigned int nr_pll, int grf_lock_offset);
 void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
-			const char **parent_names, u8 num_parents,
+			const char *const *parent_names, u8 num_parents,
 			const struct rockchip_cpuclk_reg_data *reg_data,
 			const struct rockchip_cpuclk_rate_table *rates,
 			int nrates);
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 9d70e5c03804..bebc61b5fce1 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -1156,7 +1156,7 @@ static const struct clk_ops samsung_pll2650xx_clk_min_ops = {
 };
 
 static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
-				struct samsung_pll_clock *pll_clk,
+				const struct samsung_pll_clock *pll_clk,
 				void __iomem *base)
 {
 	struct samsung_clk_pll *pll;
@@ -1303,7 +1303,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
 }
 
 void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
-			struct samsung_pll_clock *pll_list,
+			const struct samsung_pll_clock *pll_list,
 			unsigned int nr_pll, void __iomem *base)
 {
 	int cnt;
diff --git a/drivers/clk/samsung/clk-s5pv210.c b/drivers/clk/samsung/clk-s5pv210.c
index e668e479a697..cf7e8fa7b624 100644
--- a/drivers/clk/samsung/clk-s5pv210.c
+++ b/drivers/clk/samsung/clk-s5pv210.c
@@ -169,44 +169,44 @@ static inline void s5pv210_clk_sleep_init(void) { }
 #endif
 
 /* Mux parent lists. */
-static const char *fin_pll_p[] __initdata = {
+static const char *const fin_pll_p[] __initconst = {
 	"xxti",
 	"xusbxti"
 };
 
-static const char *mout_apll_p[] __initdata = {
+static const char *const mout_apll_p[] __initconst = {
 	"fin_pll",
 	"fout_apll"
 };
 
-static const char *mout_mpll_p[] __initdata = {
+static const char *const mout_mpll_p[] __initconst = {
 	"fin_pll",
 	"fout_mpll"
 };
 
-static const char *mout_epll_p[] __initdata = {
+static const char *const mout_epll_p[] __initconst = {
 	"fin_pll",
 	"fout_epll"
 };
 
-static const char *mout_vpllsrc_p[] __initdata = {
+static const char *const mout_vpllsrc_p[] __initconst = {
 	"fin_pll",
 	"sclk_hdmi27m"
 };
 
-static const char *mout_vpll_p[] __initdata = {
+static const char *const mout_vpll_p[] __initconst = {
 	"mout_vpllsrc",
 	"fout_vpll"
 };
 
-static const char *mout_group1_p[] __initdata = {
+static const char *const mout_group1_p[] __initconst = {
 	"dout_a2m",
 	"mout_mpll",
 	"mout_epll",
 	"mout_vpll"
 };
 
-static const char *mout_group2_p[] __initdata = {
+static const char *const mout_group2_p[] __initconst = {
 	"xxti",
 	"xusbxti",
 	"sclk_hdmi27m",
@@ -218,7 +218,7 @@ static const char *mout_group2_p[] __initdata = {
 	"mout_vpll",
 };
 
-static const char *mout_audio0_p[] __initdata = {
+static const char *const mout_audio0_p[] __initconst = {
 	"xxti",
 	"pcmcdclk0",
 	"sclk_hdmi27m",
@@ -230,7 +230,7 @@ static const char *mout_audio0_p[] __initdata = {
 	"mout_vpll",
 };
 
-static const char *mout_audio1_p[] __initdata = {
+static const char *const mout_audio1_p[] __initconst = {
 	"i2scdclk1",
 	"pcmcdclk1",
 	"sclk_hdmi27m",
@@ -242,7 +242,7 @@ static const char *mout_audio1_p[] __initdata = {
 	"mout_vpll",
 };
 
-static const char *mout_audio2_p[] __initdata = {
+static const char *const mout_audio2_p[] __initconst = {
 	"i2scdclk2",
 	"pcmcdclk2",
 	"sclk_hdmi27m",
@@ -254,63 +254,63 @@ static const char *mout_audio2_p[] __initdata = {
 	"mout_vpll",
 };
 
-static const char *mout_spdif_p[] __initdata = {
+static const char *const mout_spdif_p[] __initconst = {
 	"dout_audio0",
 	"dout_audio1",
 	"dout_audio3",
 };
 
-static const char *mout_group3_p[] __initdata = {
+static const char *const mout_group3_p[] __initconst = {
 	"mout_apll",
 	"mout_mpll"
 };
 
-static const char *mout_group4_p[] __initdata = {
+static const char *const mout_group4_p[] __initconst = {
 	"mout_mpll",
 	"dout_a2m"
 };
 
-static const char *mout_flash_p[] __initdata = {
+static const char *const mout_flash_p[] __initconst = {
 	"dout_hclkd",
 	"dout_hclkp"
 };
 
-static const char *mout_dac_p[] __initdata = {
+static const char *const mout_dac_p[] __initconst = {
 	"mout_vpll",
 	"sclk_hdmiphy"
 };
 
-static const char *mout_hdmi_p[] __initdata = {
+static const char *const mout_hdmi_p[] __initconst = {
 	"sclk_hdmiphy",
 	"dout_tblk"
 };
 
-static const char *mout_mixer_p[] __initdata = {
+static const char *const mout_mixer_p[] __initconst = {
 	"mout_dac",
 	"mout_hdmi"
 };
 
-static const char *mout_vpll_6442_p[] __initdata = {
+static const char *const mout_vpll_6442_p[] __initconst = {
 	"fin_pll",
 	"fout_vpll"
 };
 
-static const char *mout_mixer_6442_p[] __initdata = {
+static const char *const mout_mixer_6442_p[] __initconst = {
 	"mout_vpll",
 	"dout_mixer"
 };
 
-static const char *mout_d0sync_6442_p[] __initdata = {
+static const char *const mout_d0sync_6442_p[] __initconst = {
 	"mout_dsys",
 	"div_apll"
 };
 
-static const char *mout_d1sync_6442_p[] __initdata = {
+static const char *const mout_d1sync_6442_p[] __initconst = {
 	"mout_psys",
 	"div_apll"
 };
 
-static const char *mout_group2_6442_p[] __initdata = {
+static const char *const mout_group2_6442_p[] __initconst = {
 	"fin_pll",
 	"none",
 	"none",
@@ -322,7 +322,7 @@ static const char *mout_group2_6442_p[] __initdata = {
 	"mout_vpll",
 };
 
-static const char *mout_audio0_6442_p[] __initdata = {
+static const char *const mout_audio0_6442_p[] __initconst = {
 	"fin_pll",
 	"pcmcdclk0",
 	"none",
@@ -334,7 +334,7 @@ static const char *mout_audio0_6442_p[] __initdata = {
 	"mout_vpll",
 };
 
-static const char *mout_audio1_6442_p[] __initdata = {
+static const char *const mout_audio1_6442_p[] __initconst = {
 	"i2scdclk1",
 	"pcmcdclk1",
 	"none",
@@ -347,7 +347,7 @@ static const char *mout_audio1_6442_p[] __initdata = {
 	"fin_pll",
 };
 
-static const char *mout_clksel_p[] __initdata = {
+static const char *const mout_clksel_p[] __initconst = {
 	"fout_apll_clkout",
 	"fout_mpll_clkout",
 	"fout_epll",
@@ -370,7 +370,7 @@ static const char *mout_clksel_p[] __initdata = {
 	"div_dclk"
 };
 
-static const char *mout_clksel_6442_p[] __initdata = {
+static const char *const mout_clksel_6442_p[] __initconst = {
 	"fout_apll_clkout",
 	"fout_mpll_clkout",
 	"fout_epll",
@@ -393,7 +393,7 @@ static const char *mout_clksel_6442_p[] __initdata = {
 	"div_dclk"
 };
 
-static const char *mout_clkout_p[] __initdata = {
+static const char *const mout_clkout_p[] __initconst = {
 	"dout_clkout",
 	"none",
 	"xxti",
@@ -401,20 +401,20 @@ static const char *mout_clkout_p[] __initdata = {
 };
 
 /* Common fixed factor clocks. */
-static struct samsung_fixed_factor_clock ffactor_clks[] __initdata = {
+static const struct samsung_fixed_factor_clock ffactor_clks[] __initconst = {
 	FFACTOR(FOUT_APLL_CLKOUT, "fout_apll_clkout", "fout_apll", 1, 4, 0),
 	FFACTOR(FOUT_MPLL_CLKOUT, "fout_mpll_clkout", "fout_mpll", 1, 2, 0),
 	FFACTOR(DOUT_APLL_CLKOUT, "dout_apll_clkout", "dout_apll", 1, 4, 0),
 };
 
 /* PLL input mux (fin_pll), which needs to be registered before PLLs. */
-static struct samsung_mux_clock early_mux_clks[] __initdata = {
+static const struct samsung_mux_clock early_mux_clks[] __initconst = {
 	MUX_F(FIN_PLL, "fin_pll", fin_pll_p, OM_STAT, 0, 1,
 					CLK_MUX_READ_ONLY, 0),
 };
 
 /* Common clock muxes. */
-static struct samsung_mux_clock mux_clks[] __initdata = {
+static const struct samsung_mux_clock mux_clks[] __initconst = {
 	MUX(MOUT_FLASH, "mout_flash", mout_flash_p, CLK_SRC0, 28, 1),
 	MUX(MOUT_PSYS, "mout_psys", mout_group4_p, CLK_SRC0, 24, 1),
 	MUX(MOUT_DSYS, "mout_dsys", mout_group4_p, CLK_SRC0, 20, 1),
@@ -427,7 +427,7 @@ static struct samsung_mux_clock mux_clks[] __initdata = {
 };
 
 /* S5PV210-specific clock muxes. */
-static struct samsung_mux_clock s5pv210_mux_clks[] __initdata = {
+static const struct samsung_mux_clock s5pv210_mux_clks[] __initconst = {
 	MUX(MOUT_VPLL, "mout_vpll", mout_vpll_p, CLK_SRC0, 12, 1),
 
 	MUX(MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, CLK_SRC1, 28, 1),
@@ -472,7 +472,7 @@ static struct samsung_mux_clock s5pv210_mux_clks[] __initdata = {
 };
 
 /* S5P6442-specific clock muxes. */
-static struct samsung_mux_clock s5p6442_mux_clks[] __initdata = {
+static const struct samsung_mux_clock s5p6442_mux_clks[] __initconst = {
 	MUX(MOUT_VPLL, "mout_vpll", mout_vpll_6442_p, CLK_SRC0, 12, 1),
 
 	MUX(MOUT_FIMD, "mout_fimd", mout_group2_6442_p, CLK_SRC1, 20, 4),
@@ -504,7 +504,7 @@ static struct samsung_mux_clock s5p6442_mux_clks[] __initdata = {
 };
 
 /* S5PV210-specific fixed rate clocks generated inside the SoC. */
-static struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initconst = {
 	FRATE(SCLK_HDMI27M, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
 	FRATE(SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
 	FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
@@ -512,12 +512,12 @@ static struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initdata = {
 };
 
 /* S5P6442-specific fixed rate clocks generated inside the SoC. */
-static struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initdata = {
+static const struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initconst = {
 	FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 30000000),
 };
 
 /* Common clock dividers. */
-static struct samsung_div_clock div_clks[] __initdata = {
+static const struct samsung_div_clock div_clks[] __initconst = {
 	DIV(DOUT_PCLKP, "dout_pclkp", "dout_hclkp", CLK_DIV0, 28, 3),
 	DIV(DOUT_PCLKD, "dout_pclkd", "dout_hclkd", CLK_DIV0, 20, 3),
 	DIV(DOUT_A2M, "dout_a2m", "mout_apll", CLK_DIV0, 4, 3),
@@ -549,7 +549,7 @@ static struct samsung_div_clock div_clks[] __initdata = {
 };
 
 /* S5PV210-specific clock dividers. */
-static struct samsung_div_clock s5pv210_div_clks[] __initdata = {
+static const struct samsung_div_clock s5pv210_div_clks[] __initconst = {
 	DIV(DOUT_HCLKP, "dout_hclkp", "mout_psys", CLK_DIV0, 24, 4),
 	DIV(DOUT_HCLKD, "dout_hclkd", "mout_dsys", CLK_DIV0, 16, 4),
 	DIV(DOUT_PCLKM, "dout_pclkm", "dout_hclkm", CLK_DIV0, 12, 3),
@@ -578,7 +578,7 @@ static struct samsung_div_clock s5pv210_div_clks[] __initdata = {
 };
 
 /* S5P6442-specific clock dividers. */
-static struct samsung_div_clock s5p6442_div_clks[] __initdata = {
+static const struct samsung_div_clock s5p6442_div_clks[] __initconst = {
 	DIV(DOUT_HCLKP, "dout_hclkp", "mout_d1sync", CLK_DIV0, 24, 4),
 	DIV(DOUT_HCLKD, "dout_hclkd", "mout_d0sync", CLK_DIV0, 16, 4),
 
@@ -586,7 +586,7 @@ static struct samsung_div_clock s5p6442_div_clks[] __initdata = {
 };
 
 /* Common clock gates. */
-static struct samsung_gate_clock gate_clks[] __initdata = {
+static const struct samsung_gate_clock gate_clks[] __initconst = {
 	GATE(CLK_ROTATOR, "rotator", "dout_hclkd", CLK_GATE_IP0, 29, 0, 0),
 	GATE(CLK_FIMC2, "fimc2", "dout_hclkd", CLK_GATE_IP0, 26, 0, 0),
 	GATE(CLK_FIMC1, "fimc1", "dout_hclkd", CLK_GATE_IP0, 25, 0, 0),
@@ -666,7 +666,7 @@ static struct samsung_gate_clock gate_clks[] __initdata = {
 };
 
 /* S5PV210-specific clock gates. */
-static struct samsung_gate_clock s5pv210_gate_clks[] __initdata = {
+static const struct samsung_gate_clock s5pv210_gate_clks[] __initconst = {
 	GATE(CLK_CSIS, "clk_csis", "dout_hclkd", CLK_GATE_IP0, 31, 0, 0),
 	GATE(CLK_MFC, "mfc", "dout_hclkm", CLK_GATE_IP0, 16, 0, 0),
 	GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
@@ -728,7 +728,7 @@ static struct samsung_gate_clock s5pv210_gate_clks[] __initdata = {
 };
 
 /* S5P6442-specific clock gates. */
-static struct samsung_gate_clock s5p6442_gate_clks[] __initdata = {
+static const struct samsung_gate_clock s5p6442_gate_clks[] __initconst = {
 	GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP0, 28, 0, 0),
 	GATE(CLK_MFC, "mfc", "dout_hclkd", CLK_GATE_IP0, 16, 0, 0),
 	GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
@@ -748,14 +748,14 @@ static struct samsung_gate_clock s5p6442_gate_clks[] __initdata = {
  * Clock aliases for legacy clkdev look-up.
  * NOTE: Needed only to support legacy board files.
  */
-static struct samsung_clock_alias s5pv210_aliases[] = {
+static const struct samsung_clock_alias s5pv210_aliases[] __initconst = {
 	ALIAS(DOUT_APLL, NULL, "armclk"),
 	ALIAS(DOUT_HCLKM, NULL, "hclk_msys"),
 	ALIAS(MOUT_DMC0, NULL, "sclk_dmc0"),
 };
 
 /* S5PV210-specific PLLs. */
-static struct samsung_pll_clock s5pv210_pll_clks[] __initdata = {
+static const struct samsung_pll_clock s5pv210_pll_clks[] __initconst = {
 	[apll] = PLL(pll_4508, FOUT_APLL, "fout_apll", "fin_pll",
 						APLL_LOCK, APLL_CON0, NULL),
 	[mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
@@ -767,7 +767,7 @@ static struct samsung_pll_clock s5pv210_pll_clks[] __initdata = {
 };
 
 /* S5P6442-specific PLLs. */
-static struct samsung_pll_clock s5p6442_pll_clks[] __initdata = {
+static const struct samsung_pll_clock s5p6442_pll_clks[] __initconst = {
 	[apll] = PLL(pll_4502, FOUT_APLL, "fout_apll", "fin_pll",
 						APLL_LOCK, APLL_CON0, NULL),
 	[mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
index 76491629d1e5..0117238391d6 100644
--- a/drivers/clk/samsung/clk.c
+++ b/drivers/clk/samsung/clk.c
@@ -98,7 +98,7 @@ void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk,
 
 /* register a list of aliases */
 void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
-				struct samsung_clock_alias *list,
+				const struct samsung_clock_alias *list,
 				unsigned int nr_clk)
 {
 	struct clk *clk;
@@ -132,7 +132,8 @@ void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
 
 /* register a list of fixed clocks */
 void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
-		struct samsung_fixed_rate_clock *list, unsigned int nr_clk)
+		const struct samsung_fixed_rate_clock *list,
+		unsigned int nr_clk)
 {
 	struct clk *clk;
 	unsigned int idx, ret;
@@ -161,7 +162,7 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
 
 /* register a list of fixed factor clocks */
 void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
-		struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
+		const struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
 {
 	struct clk *clk;
 	unsigned int idx;
@@ -181,7 +182,7 @@ void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
 
 /* register a list of mux clocks */
 void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
-				struct samsung_mux_clock *list,
+				const struct samsung_mux_clock *list,
 				unsigned int nr_clk)
 {
 	struct clk *clk;
@@ -213,7 +214,7 @@ void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
 
 /* register a list of div clocks */
 void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
-				struct samsung_div_clock *list,
+				const struct samsung_div_clock *list,
 				unsigned int nr_clk)
 {
 	struct clk *clk;
@@ -252,7 +253,7 @@ void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
 
 /* register a list of gate clocks */
 void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
-				struct samsung_gate_clock *list,
+				const struct samsung_gate_clock *list,
 				unsigned int nr_clk)
 {
 	struct clk *clk;
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
index e4c75383cea7..b775fc29caa5 100644
--- a/drivers/clk/samsung/clk.h
+++ b/drivers/clk/samsung/clk.h
@@ -121,7 +121,7 @@ struct samsung_mux_clock {
 	unsigned int		id;
 	const char		*dev_name;
 	const char		*name;
-	const char		**parent_names;
+	const char		*const *parent_names;
 	u8			num_parents;
 	unsigned long		flags;
 	unsigned long		offset;
@@ -368,28 +368,28 @@ extern void __init samsung_clk_of_register_fixed_ext(
 extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,
 			struct clk *clk, unsigned int id);
 
-extern void samsung_clk_register_alias(struct samsung_clk_provider *ctx,
-			struct samsung_clock_alias *list,
+extern void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx,
+			const struct samsung_clock_alias *list,
 			unsigned int nr_clk);
 extern void __init samsung_clk_register_fixed_rate(
 			struct samsung_clk_provider *ctx,
-			struct samsung_fixed_rate_clock *clk_list,
+			const struct samsung_fixed_rate_clock *clk_list,
 			unsigned int nr_clk);
 extern void __init samsung_clk_register_fixed_factor(
 			struct samsung_clk_provider *ctx,
-			struct samsung_fixed_factor_clock *list,
+			const struct samsung_fixed_factor_clock *list,
 			unsigned int nr_clk);
 extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx,
-			struct samsung_mux_clock *clk_list,
+			const struct samsung_mux_clock *clk_list,
 			unsigned int nr_clk);
 extern void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
-			struct samsung_div_clock *clk_list,
+			const struct samsung_div_clock *clk_list,
 			unsigned int nr_clk);
 extern void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx,
-			struct samsung_gate_clock *clk_list,
+			const struct samsung_gate_clock *clk_list,
 			unsigned int nr_clk);
 extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
-			struct samsung_pll_clock *pll_list,
+			const struct samsung_pll_clock *pll_list,
 			unsigned int nr_clk, void __iomem *base);
 
 extern struct samsung_clk_provider __init *samsung_cmu_register_one(
diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c
index 40cb113be6af..de614384bb44 100644
--- a/drivers/clk/zynq/clkc.c
+++ b/drivers/clk/zynq/clkc.c
@@ -85,22 +85,29 @@ static DEFINE_SPINLOCK(canmioclk_lock);
 static DEFINE_SPINLOCK(dbgclk_lock);
 static DEFINE_SPINLOCK(aperclk_lock);
 
-static const char *armpll_parents[] __initdata = {"armpll_int", "ps_clk"};
-static const char *ddrpll_parents[] __initdata = {"ddrpll_int", "ps_clk"};
-static const char *iopll_parents[] __initdata = {"iopll_int", "ps_clk"};
+static const char *const armpll_parents[] __initconst = {"armpll_int",
+	"ps_clk"};
+static const char *const ddrpll_parents[] __initconst = {"ddrpll_int",
+	"ps_clk"};
+static const char *const iopll_parents[] __initconst = {"iopll_int",
+	"ps_clk"};
 static const char *gem0_mux_parents[] __initdata = {"gem0_div1", "dummy_name"};
 static const char *gem1_mux_parents[] __initdata = {"gem1_div1", "dummy_name"};
-static const char *can0_mio_mux2_parents[] __initdata = {"can0_gate",
+static const char *const can0_mio_mux2_parents[] __initconst = {"can0_gate",
 	"can0_mio_mux"};
-static const char *can1_mio_mux2_parents[] __initdata = {"can1_gate",
+static const char *const can1_mio_mux2_parents[] __initconst = {"can1_gate",
 	"can1_mio_mux"};
 static const char *dbg_emio_mux_parents[] __initdata = {"dbg_div",
 	"dummy_name"};
 
-static const char *dbgtrc_emio_input_names[] __initdata = {"trace_emio_clk"};
-static const char *gem0_emio_input_names[] __initdata = {"gem0_emio_clk"};
-static const char *gem1_emio_input_names[] __initdata = {"gem1_emio_clk"};
-static const char *swdt_ext_clk_input_names[] __initdata = {"swdt_ext_clk"};
+static const char *const dbgtrc_emio_input_names[] __initconst = {
+	"trace_emio_clk"};
+static const char *const gem0_emio_input_names[] __initconst = {
+	"gem0_emio_clk"};
+static const char *const gem1_emio_input_names[] __initconst = {
+	"gem1_emio_clk"};
+static const char *const swdt_ext_clk_input_names[] __initconst = {
+	"swdt_ext_clk"};
 
 static void __init zynq_clk_register_fclk(enum zynq_clk fclk,
 		const char *clk_name, void __iomem *fclk_ctrl_reg,

From 7a29a869434e8b7a71972227f0920e2f8ea777bd Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Mon, 1 Jun 2015 13:13:53 +0200
Subject: [PATCH 102/135] clk: meson: Add support for Meson clock controller

This patchset adds the infrastructure for registering and managing the
core clocks found on Amlogic MesonX SoCs. In particular:

- PLLs
- CPU clock
- Fixed rate clocks, fixed factor clocks, ...

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/Makefile                     |   1 +
 drivers/clk/meson/Makefile               |   5 +
 drivers/clk/meson/clk-cpu.c              | 234 +++++++++++++++++++++
 drivers/clk/meson/clk-pll.c              | 227 ++++++++++++++++++++
 drivers/clk/meson/clkc.c                 | 250 +++++++++++++++++++++++
 drivers/clk/meson/clkc.h                 | 187 +++++++++++++++++
 include/dt-bindings/clock/meson8b-clkc.h |  25 +++
 7 files changed, 929 insertions(+)
 create mode 100644 drivers/clk/meson/Makefile
 create mode 100644 drivers/clk/meson/clk-cpu.c
 create mode 100644 drivers/clk/meson/clk-pll.c
 create mode 100644 drivers/clk/meson/clkc.c
 create mode 100644 drivers/clk/meson/clkc.h
 create mode 100644 include/dt-bindings/clock/meson8b-clkc.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 3d00c25382c5..9c4ddb1b0845 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -55,6 +55,7 @@ ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)			+= mmp/
 endif
 obj-$(CONFIG_PLAT_ORION)		+= mvebu/
+obj-$(CONFIG_ARCH_MESON)		+= meson/
 obj-$(CONFIG_ARCH_MXS)			+= mxs/
 obj-$(CONFIG_MACH_PISTACHIO)		+= pistachio/
 obj-$(CONFIG_COMMON_CLK_PXA)		+= pxa/
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
new file mode 100644
index 000000000000..66c6d8d23553
--- /dev/null
+++ b/drivers/clk/meson/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for Meson specific clk
+#
+
+obj-y += clkc.o clk-pll.o clk-cpu.o
diff --git a/drivers/clk/meson/clk-cpu.c b/drivers/clk/meson/clk-cpu.c
new file mode 100644
index 000000000000..148e99fc5970
--- /dev/null
+++ b/drivers/clk/meson/clk-cpu.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * CPU clock path:
+ *
+ *                           +-[/N]-----|3|
+ *             MUX2  +--[/3]-+----------|2| MUX1
+ * [sys_pll]---|1|   |--[/2]------------|1|-|1|
+ *             | |---+------------------|0| | |----- [a5_clk]
+ *          +--|0|                          | |
+ * [xtal]---+-------------------------------|0|
+ *
+ *
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+
+#define MESON_CPU_CLK_CNTL1		0x00
+#define MESON_CPU_CLK_CNTL		0x40
+
+#define MESON_CPU_CLK_MUX1		BIT(7)
+#define MESON_CPU_CLK_MUX2		BIT(0)
+
+#define MESON_N_WIDTH			9
+#define MESON_N_SHIFT			20
+#define MESON_SEL_WIDTH			2
+#define MESON_SEL_SHIFT			2
+
+#include "clkc.h"
+
+struct meson_clk_cpu {
+	struct notifier_block		clk_nb;
+	const struct clk_div_table	*div_table;
+	struct clk_hw			hw;
+	void __iomem			*base;
+	u16				reg_off;
+};
+#define to_meson_clk_cpu_hw(_hw) container_of(_hw, struct meson_clk_cpu, hw)
+#define to_meson_clk_cpu_nb(_nb) container_of(_nb, struct meson_clk_cpu, clk_nb)
+
+static long meson_clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long *prate)
+{
+	struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
+
+	return divider_round_rate(hw, rate, prate, clk_cpu->div_table,
+				  MESON_N_WIDTH, CLK_DIVIDER_ROUND_CLOSEST);
+}
+
+static int meson_clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long parent_rate)
+{
+	struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
+	unsigned int div, sel, N = 0;
+	u32 reg;
+
+	div = DIV_ROUND_UP(parent_rate, rate);
+
+	if (div <= 3) {
+		sel = div - 1;
+	} else {
+		sel = 3;
+		N = div / 2;
+	}
+
+	reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
+	reg = PARM_SET(MESON_N_WIDTH, MESON_N_SHIFT, reg, N);
+	writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
+
+	reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
+	reg = PARM_SET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg, sel);
+	writel(reg, clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
+
+	return 0;
+}
+
+static unsigned long meson_clk_cpu_recalc_rate(struct clk_hw *hw,
+					       unsigned long parent_rate)
+{
+	struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_hw(hw);
+	unsigned int N, sel;
+	unsigned int div = 1;
+	u32 reg;
+
+	reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL1);
+	N = PARM_GET(MESON_N_WIDTH, MESON_N_SHIFT, reg);
+
+	reg = readl(clk_cpu->base + clk_cpu->reg_off + MESON_CPU_CLK_CNTL);
+	sel = PARM_GET(MESON_SEL_WIDTH, MESON_SEL_SHIFT, reg);
+
+	if (sel < 3)
+		div = sel + 1;
+	else
+		div = 2 * N;
+
+	return parent_rate / div;
+}
+
+static int meson_clk_cpu_pre_rate_change(struct meson_clk_cpu *clk_cpu,
+					 struct clk_notifier_data *ndata)
+{
+	u32 cpu_clk_cntl;
+
+	/* switch MUX1 to xtal */
+	cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off
+				+ MESON_CPU_CLK_CNTL);
+	cpu_clk_cntl &= ~MESON_CPU_CLK_MUX1;
+	writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
+				+ MESON_CPU_CLK_CNTL);
+	udelay(100);
+
+	/* switch MUX2 to sys-pll */
+	cpu_clk_cntl |= MESON_CPU_CLK_MUX2;
+	writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
+				+ MESON_CPU_CLK_CNTL);
+
+	return 0;
+}
+
+static int meson_clk_cpu_post_rate_change(struct meson_clk_cpu *clk_cpu,
+					  struct clk_notifier_data *ndata)
+{
+	u32 cpu_clk_cntl;
+
+	/* switch MUX1 to divisors' output */
+	cpu_clk_cntl = readl(clk_cpu->base + clk_cpu->reg_off
+				+ MESON_CPU_CLK_CNTL);
+	cpu_clk_cntl |= MESON_CPU_CLK_MUX1;
+	writel(cpu_clk_cntl, clk_cpu->base + clk_cpu->reg_off
+				+ MESON_CPU_CLK_CNTL);
+	udelay(100);
+
+	return 0;
+}
+
+/*
+ * This clock notifier is called when the frequency of the of the parent
+ * PLL clock is to be changed. We use the xtal input as temporary parent
+ * while the PLL frequency is stabilized.
+ */
+static int meson_clk_cpu_notifier_cb(struct notifier_block *nb,
+				     unsigned long event, void *data)
+{
+	struct clk_notifier_data *ndata = data;
+	struct meson_clk_cpu *clk_cpu = to_meson_clk_cpu_nb(nb);
+	int ret = 0;
+
+	if (event == PRE_RATE_CHANGE)
+		ret = meson_clk_cpu_pre_rate_change(clk_cpu, ndata);
+	else if (event == POST_RATE_CHANGE)
+		ret = meson_clk_cpu_post_rate_change(clk_cpu, ndata);
+
+	return notifier_from_errno(ret);
+}
+
+static const struct clk_ops meson_clk_cpu_ops = {
+	.recalc_rate	= meson_clk_cpu_recalc_rate,
+	.round_rate	= meson_clk_cpu_round_rate,
+	.set_rate	= meson_clk_cpu_set_rate,
+};
+
+struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf,
+				   void __iomem *reg_base,
+				   spinlock_t *lock)
+{
+	struct clk *clk;
+	struct clk *pclk;
+	struct meson_clk_cpu *clk_cpu;
+	struct clk_init_data init;
+	int ret;
+
+	clk_cpu = kzalloc(sizeof(*clk_cpu), GFP_KERNEL);
+	if (!clk_cpu)
+		return ERR_PTR(-ENOMEM);
+
+	clk_cpu->base = reg_base;
+	clk_cpu->reg_off = clk_conf->reg_off;
+	clk_cpu->div_table = clk_conf->conf.div_table;
+	clk_cpu->clk_nb.notifier_call = meson_clk_cpu_notifier_cb;
+
+	init.name = clk_conf->clk_name;
+	init.ops = &meson_clk_cpu_ops;
+	init.flags = clk_conf->flags | CLK_GET_RATE_NOCACHE;
+	init.flags |= CLK_SET_RATE_PARENT;
+	init.parent_names = clk_conf->clks_parent;
+	init.num_parents = 1;
+
+	clk_cpu->hw.init = &init;
+
+	pclk = __clk_lookup(clk_conf->clks_parent[0]);
+	if (!pclk) {
+		pr_err("%s: could not lookup parent clock %s\n",
+				__func__, clk_conf->clks_parent[0]);
+		return ERR_PTR(-EINVAL);
+	}
+
+	ret = clk_notifier_register(pclk, &clk_cpu->clk_nb);
+	if (ret) {
+		pr_err("%s: failed to register clock notifier for %s\n",
+				__func__, clk_conf->clk_name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	clk = clk_register(NULL, &clk_cpu->hw);
+	if (IS_ERR(clk)) {
+		clk_notifier_unregister(pclk, &clk_cpu->clk_nb);
+		kfree(clk_cpu);
+	}
+
+	return clk;
+}
+
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
new file mode 100644
index 000000000000..664edf0708ea
--- /dev/null
+++ b/drivers/clk/meson/clk-pll.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * In the most basic form, a Meson PLL is composed as follows:
+ *
+ *                     PLL
+ *      +------------------------------+
+ *      |                              |
+ * in -----[ /N ]---[ *M ]---[ >>OD ]----->> out
+ *      |         ^        ^           |
+ *      +------------------------------+
+ *                |        |
+ *               FREF     VCO
+ *
+ * out = (in * M / N) >> OD
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "clkc.h"
+
+#define MESON_PLL_RESET				BIT(29)
+#define MESON_PLL_LOCK				BIT(31)
+
+struct meson_clk_pll {
+	struct clk_hw	hw;
+	void __iomem	*base;
+	struct pll_conf	*conf;
+	unsigned int	rate_count;
+	spinlock_t	*lock;
+};
+#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
+
+static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
+{
+	struct meson_clk_pll *pll = to_meson_clk_pll(hw);
+	struct parm *p;
+	unsigned long parent_rate_mhz = parent_rate / 1000000;
+	unsigned long rate_mhz;
+	u16 n, m, od;
+	u32 reg;
+
+	p = &pll->conf->n;
+	reg = readl(pll->base + p->reg_off);
+	n = PARM_GET(p->width, p->shift, reg);
+
+	p = &pll->conf->m;
+	reg = readl(pll->base + p->reg_off);
+	m = PARM_GET(p->width, p->shift, reg);
+
+	p = &pll->conf->od;
+	reg = readl(pll->base + p->reg_off);
+	od = PARM_GET(p->width, p->shift, reg);
+
+	rate_mhz = (parent_rate_mhz * m / n) >> od;
+
+	return rate_mhz * 1000000;
+}
+
+static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long *parent_rate)
+{
+	struct meson_clk_pll *pll = to_meson_clk_pll(hw);
+	const struct pll_rate_table *rate_table = pll->conf->rate_table;
+	int i;
+
+	for (i = 0; i < pll->rate_count; i++) {
+		if (rate <= rate_table[i].rate)
+			return rate_table[i].rate;
+	}
+
+	/* else return the smallest value */
+	return rate_table[0].rate;
+}
+
+static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_pll *pll,
+							       unsigned long rate)
+{
+	const struct pll_rate_table *rate_table = pll->conf->rate_table;
+	int i;
+
+	for (i = 0; i < pll->rate_count; i++) {
+		if (rate == rate_table[i].rate)
+			return &rate_table[i];
+	}
+	return NULL;
+}
+
+static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
+				   struct parm *p_n)
+{
+	int delay = 24000000;
+	u32 reg;
+
+	while (delay > 0) {
+		reg = readl(pll->base + p_n->reg_off);
+
+		if (reg & MESON_PLL_LOCK)
+			return 0;
+		delay--;
+	}
+	return -ETIMEDOUT;
+}
+
+static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long parent_rate)
+{
+	struct meson_clk_pll *pll = to_meson_clk_pll(hw);
+	struct parm *p;
+	const struct pll_rate_table *rate_set;
+	unsigned long old_rate;
+	int ret = 0;
+	u32 reg;
+
+	if (parent_rate == 0 || rate == 0)
+		return -EINVAL;
+
+	old_rate = rate;
+
+	rate_set = meson_clk_get_pll_settings(pll, rate);
+	if (!rate_set)
+		return -EINVAL;
+
+	/* PLL reset */
+	p = &pll->conf->n;
+	reg = readl(pll->base + p->reg_off);
+	writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
+
+	reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
+	writel(reg, pll->base + p->reg_off);
+
+	p = &pll->conf->m;
+	reg = readl(pll->base + p->reg_off);
+	reg = PARM_SET(p->width, p->shift, reg, rate_set->m);
+	writel(reg, pll->base + p->reg_off);
+
+	p = &pll->conf->od;
+	reg = readl(pll->base + p->reg_off);
+	reg = PARM_SET(p->width, p->shift, reg, rate_set->od);
+	writel(reg, pll->base + p->reg_off);
+
+	p = &pll->conf->n;
+	ret = meson_clk_pll_wait_lock(pll, p);
+	if (ret) {
+		pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
+			__func__, old_rate);
+		meson_clk_pll_set_rate(hw, old_rate, parent_rate);
+	}
+
+	return ret;
+}
+
+static const struct clk_ops meson_clk_pll_ops = {
+	.recalc_rate	= meson_clk_pll_recalc_rate,
+	.round_rate	= meson_clk_pll_round_rate,
+	.set_rate	= meson_clk_pll_set_rate,
+};
+
+static const struct clk_ops meson_clk_pll_ro_ops = {
+	.recalc_rate	= meson_clk_pll_recalc_rate,
+};
+
+struct clk *meson_clk_register_pll(const struct clk_conf *clk_conf,
+				   void __iomem *reg_base,
+				   spinlock_t *lock)
+{
+	struct clk *clk;
+	struct meson_clk_pll *clk_pll;
+	struct clk_init_data init;
+
+	clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
+	if (!clk_pll)
+		return ERR_PTR(-ENOMEM);
+
+	clk_pll->base = reg_base + clk_conf->reg_off;
+	clk_pll->lock = lock;
+	clk_pll->conf = clk_conf->conf.pll;
+
+	init.name = clk_conf->clk_name;
+	init.flags = clk_conf->flags | CLK_GET_RATE_NOCACHE;
+
+	init.parent_names = &clk_conf->clks_parent[0];
+	init.num_parents = 1;
+	init.ops = &meson_clk_pll_ro_ops;
+
+	/* If no rate_table is specified we assume the PLL is read-only */
+	if (clk_pll->conf->rate_table) {
+		int len;
+
+		for (len = 0; clk_pll->conf->rate_table[len].rate != 0; )
+			len++;
+
+		 clk_pll->rate_count = len;
+		 init.ops = &meson_clk_pll_ops;
+	}
+
+	clk_pll->hw.init = &init;
+
+	clk = clk_register(NULL, &clk_pll->hw);
+	if (IS_ERR(clk))
+		kfree(clk_pll);
+
+	return clk;
+}
diff --git a/drivers/clk/meson/clkc.c b/drivers/clk/meson/clkc.c
new file mode 100644
index 000000000000..b8c511c5e7a7
--- /dev/null
+++ b/drivers/clk/meson/clkc.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/slab.h>
+
+#include "clkc.h"
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static struct clk **clks;
+static struct clk_onecell_data clk_data;
+
+struct clk ** __init meson_clk_init(struct device_node *np,
+				   unsigned long nr_clks)
+{
+	clks = kcalloc(nr_clks, sizeof(*clks), GFP_KERNEL);
+	if (!clks)
+		return ERR_PTR(-ENOMEM);
+
+	clk_data.clks = clks;
+	clk_data.clk_num = nr_clks;
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+	return clks;
+}
+
+static void meson_clk_add_lookup(struct clk *clk, unsigned int id)
+{
+	if (clks && id)
+		clks[id] = clk;
+}
+
+static struct clk * __init
+meson_clk_register_composite(const struct clk_conf *clk_conf,
+			     void __iomem *clk_base)
+{
+	struct clk *clk;
+	struct clk_mux *mux = NULL;
+	struct clk_divider *div = NULL;
+	struct clk_gate *gate = NULL;
+	const struct clk_ops *mux_ops = NULL;
+	const struct composite_conf *composite_conf;
+
+	composite_conf = clk_conf->conf.composite;
+
+	if (clk_conf->num_parents > 1) {
+		mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+		if (!mux)
+			return ERR_PTR(-ENOMEM);
+
+		mux->reg = clk_base + clk_conf->reg_off
+				+ composite_conf->mux_parm.reg_off;
+		mux->shift = composite_conf->mux_parm.shift;
+		mux->mask = BIT(composite_conf->mux_parm.width) - 1;
+		mux->flags = composite_conf->mux_flags;
+		mux->lock = &clk_lock;
+		mux->table = composite_conf->mux_table;
+		mux_ops = (composite_conf->mux_flags & CLK_MUX_READ_ONLY) ?
+			  &clk_mux_ro_ops : &clk_mux_ops;
+	}
+
+	if (MESON_PARM_APPLICABLE(&composite_conf->div_parm)) {
+		div = kzalloc(sizeof(*div), GFP_KERNEL);
+		if (!div) {
+			clk = ERR_PTR(-ENOMEM);
+			goto error;
+		}
+
+		div->reg = clk_base + clk_conf->reg_off
+				+ composite_conf->div_parm.reg_off;
+		div->shift = composite_conf->div_parm.shift;
+		div->width = composite_conf->div_parm.width;
+		div->lock = &clk_lock;
+		div->flags = composite_conf->div_flags;
+		div->table = composite_conf->div_table;
+	}
+
+	if (MESON_PARM_APPLICABLE(&composite_conf->gate_parm)) {
+		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+		if (!gate) {
+			clk = ERR_PTR(-ENOMEM);
+			goto error;
+		}
+
+		gate->reg = clk_base + clk_conf->reg_off
+				+ composite_conf->div_parm.reg_off;
+		gate->bit_idx = composite_conf->gate_parm.shift;
+		gate->flags = composite_conf->gate_flags;
+		gate->lock = &clk_lock;
+	}
+
+	clk = clk_register_composite(NULL, clk_conf->clk_name,
+				    clk_conf->clks_parent,
+				    clk_conf->num_parents,
+				    mux ? &mux->hw : NULL, mux_ops,
+				    div ? &div->hw : NULL, &clk_divider_ops,
+				    gate ? &gate->hw : NULL, &clk_gate_ops,
+				    clk_conf->flags);
+	if (IS_ERR(clk))
+		goto error;
+
+	return clk;
+
+error:
+	kfree(gate);
+	kfree(div);
+	kfree(mux);
+
+	return clk;
+}
+
+static struct clk * __init
+meson_clk_register_fixed_factor(const struct clk_conf *clk_conf,
+				void __iomem *clk_base)
+{
+	struct clk *clk;
+	const struct fixed_fact_conf *fixed_fact_conf;
+	const struct parm *p;
+	unsigned int mult, div;
+	u32 reg;
+
+	fixed_fact_conf = &clk_conf->conf.fixed_fact;
+
+	mult = clk_conf->conf.fixed_fact.mult;
+	div = clk_conf->conf.fixed_fact.div;
+
+	if (!mult) {
+		mult = 1;
+		p = &fixed_fact_conf->mult_parm;
+		if (MESON_PARM_APPLICABLE(p)) {
+			reg = readl(clk_base + clk_conf->reg_off + p->reg_off);
+			mult = PARM_GET(p->width, p->shift, reg);
+		}
+	}
+
+	if (!div) {
+		div = 1;
+		p = &fixed_fact_conf->div_parm;
+		if (MESON_PARM_APPLICABLE(p)) {
+			reg = readl(clk_base + clk_conf->reg_off + p->reg_off);
+			mult = PARM_GET(p->width, p->shift, reg);
+		}
+	}
+
+	clk = clk_register_fixed_factor(NULL,
+			clk_conf->clk_name,
+			clk_conf->clks_parent[0],
+			clk_conf->flags,
+			mult, div);
+
+	return clk;
+}
+
+static struct clk * __init
+meson_clk_register_fixed_rate(const struct clk_conf *clk_conf,
+			      void __iomem *clk_base)
+{
+	struct clk *clk;
+	const struct fixed_rate_conf *fixed_rate_conf;
+	const struct parm *r;
+	unsigned long rate;
+	u32 reg;
+
+	fixed_rate_conf = &clk_conf->conf.fixed_rate;
+	rate = fixed_rate_conf->rate;
+
+	if (!rate) {
+		r = &fixed_rate_conf->rate_parm;
+		reg = readl(clk_base + clk_conf->reg_off + r->reg_off);
+		rate = PARM_GET(r->width, r->shift, reg);
+	}
+
+	rate *= 1000000;
+
+	clk = clk_register_fixed_rate(NULL,
+			clk_conf->clk_name,
+			clk_conf->num_parents
+				? clk_conf->clks_parent[0] : NULL,
+			clk_conf->flags, rate);
+
+	return clk;
+}
+
+void __init meson_clk_register_clks(const struct clk_conf *clk_confs,
+				    size_t nr_confs,
+				    void __iomem *clk_base)
+{
+	unsigned int i;
+	struct clk *clk = NULL;
+
+	for (i = 0; i < nr_confs; i++) {
+		const struct clk_conf *clk_conf = &clk_confs[i];
+
+		switch (clk_conf->clk_type) {
+		case CLK_FIXED_RATE:
+			clk = meson_clk_register_fixed_rate(clk_conf,
+							    clk_base);
+			break;
+		case CLK_FIXED_FACTOR:
+			clk = meson_clk_register_fixed_factor(clk_conf,
+							      clk_base);
+			break;
+		case CLK_COMPOSITE:
+			clk = meson_clk_register_composite(clk_conf,
+							   clk_base);
+			break;
+		case CLK_CPU:
+			clk = meson_clk_register_cpu(clk_conf, clk_base,
+						     &clk_lock);
+			break;
+		case CLK_PLL:
+			clk = meson_clk_register_pll(clk_conf, clk_base,
+						     &clk_lock);
+			break;
+		default:
+			clk = NULL;
+		}
+
+		if (!clk) {
+			pr_err("%s: unknown clock type %d\n", __func__,
+			       clk_conf->clk_type);
+			continue;
+		}
+
+		if (IS_ERR(clk)) {
+			pr_warn("%s: Unable to create %s clock\n", __func__,
+				clk_conf->clk_name);
+			continue;
+		}
+
+		meson_clk_add_lookup(clk, clk_conf->clk_id);
+	}
+}
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
new file mode 100644
index 000000000000..609ae92cc13f
--- /dev/null
+++ b/drivers/clk/meson/clkc.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __CLKC_H
+#define __CLKC_H
+
+#define PMASK(width)			GENMASK(width - 1, 0)
+#define SETPMASK(width, shift)		GENMASK(shift + width - 1, shift)
+#define CLRPMASK(width, shift)		(~SETPMASK(width, shift))
+
+#define PARM_GET(width, shift, reg)					\
+	(((reg) & SETPMASK(width, shift)) >> (shift))
+#define PARM_SET(width, shift, reg, val)				\
+	(((reg) & CLRPMASK(width, shift)) | (val << (shift)))
+
+#define MESON_PARM_APPLICABLE(p)		(!!((p)->width))
+
+struct parm {
+	u16	reg_off;
+	u8	shift;
+	u8	width;
+};
+#define PARM(_r, _s, _w)						\
+	{								\
+		.reg_off	= (_r),					\
+		.shift		= (_s),					\
+		.width		= (_w),					\
+	}								\
+
+struct pll_rate_table {
+	unsigned long	rate;
+	u16		m;
+	u16		n;
+	u16		od;
+};
+#define PLL_RATE(_r, _m, _n, _od)					\
+	{								\
+		.rate		= (_r),					\
+		.m		= (_m),					\
+		.n		= (_n),					\
+		.od		= (_od),				\
+	}								\
+
+struct pll_conf {
+	const struct pll_rate_table	*rate_table;
+	struct parm			m;
+	struct parm			n;
+	struct parm			od;
+};
+
+struct fixed_fact_conf {
+	unsigned int	div;
+	unsigned int	mult;
+	struct parm	div_parm;
+	struct parm	mult_parm;
+};
+
+struct fixed_rate_conf {
+	unsigned long	rate;
+	struct parm	rate_parm;
+};
+
+struct composite_conf {
+	struct parm		mux_parm;
+	struct parm		div_parm;
+	struct parm		gate_parm;
+	struct clk_div_table	*div_table;
+	u32			*mux_table;
+	u8			mux_flags;
+	u8			div_flags;
+	u8			gate_flags;
+};
+
+#define PNAME(x) static const char *x[]
+
+enum clk_type {
+	CLK_FIXED_FACTOR,
+	CLK_FIXED_RATE,
+	CLK_COMPOSITE,
+	CLK_CPU,
+	CLK_PLL,
+};
+
+struct clk_conf {
+	u16				reg_off;
+	enum clk_type			clk_type;
+	unsigned int			clk_id;
+	const char			*clk_name;
+	const char			**clks_parent;
+	int				num_parents;
+	unsigned long			flags;
+	union {
+		struct fixed_fact_conf		fixed_fact;
+		struct fixed_rate_conf		fixed_rate;
+		const struct composite_conf		*composite;
+		struct pll_conf			*pll;
+		const struct clk_div_table	*div_table;
+	} conf;
+};
+
+#define FIXED_RATE_P(_ro, _ci, _cn, _f, _c)				\
+	{								\
+		.reg_off			= (_ro),		\
+		.clk_type			= CLK_FIXED_RATE,	\
+		.clk_id				= (_ci),		\
+		.clk_name			= (_cn),		\
+		.flags				= (_f),			\
+		.conf.fixed_rate.rate_parm	= _c,			\
+	}								\
+
+#define FIXED_RATE(_ci, _cn, _f, _r)					\
+	{								\
+		.clk_type			= CLK_FIXED_RATE,	\
+		.clk_id				= (_ci),		\
+		.clk_name			= (_cn),		\
+		.flags				= (_f),			\
+		.conf.fixed_rate.rate		= (_r),			\
+	}								\
+
+#define PLL(_ro, _ci, _cn, _cp, _f, _c)					\
+	{								\
+		.reg_off			= (_ro),		\
+		.clk_type			= CLK_PLL,		\
+		.clk_id				= (_ci),		\
+		.clk_name			= (_cn),		\
+		.clks_parent			= (_cp),		\
+		.num_parents			= ARRAY_SIZE(_cp),	\
+		.flags				= (_f),			\
+		.conf.pll			= (_c),			\
+	}								\
+
+#define FIXED_FACTOR_DIV(_ci, _cn, _cp, _f, _d)				\
+	{								\
+		.clk_type			= CLK_FIXED_FACTOR,	\
+		.clk_id				= (_ci),		\
+		.clk_name			= (_cn),		\
+		.clks_parent			= (_cp),		\
+		.num_parents			= ARRAY_SIZE(_cp),	\
+		.conf.fixed_fact.div		= (_d),			\
+	}								\
+
+#define CPU(_ro, _ci, _cn, _cp, _dt)					\
+	{								\
+		.reg_off			= (_ro),		\
+		.clk_type			= CLK_CPU,		\
+		.clk_id				= (_ci),		\
+		.clk_name			= (_cn),		\
+		.clks_parent			= (_cp),		\
+		.num_parents			= ARRAY_SIZE(_cp),	\
+		.conf.div_table			= (_dt),		\
+	}								\
+
+#define COMPOSITE(_ro, _ci, _cn, _cp, _f, _c)				\
+	{								\
+		.reg_off			= (_ro),		\
+		.clk_type			= CLK_COMPOSITE,	\
+		.clk_id				= (_ci),		\
+		.clk_name			= (_cn),		\
+		.clks_parent			= (_cp),		\
+		.num_parents			= ARRAY_SIZE(_cp),	\
+		.flags				= (_f),			\
+		.conf.composite			= (_c),			\
+	}								\
+
+struct clk **meson_clk_init(struct device_node *np, unsigned long nr_clks);
+void meson_clk_register_clks(const struct clk_conf *clk_confs,
+			     unsigned int nr_confs, void __iomem *clk_base);
+struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf,
+				   void __iomem *reg_base, spinlock_t *lock);
+struct clk *meson_clk_register_pll(const struct clk_conf *clk_conf,
+				   void __iomem *reg_base, spinlock_t *lock);
+
+#endif /* __CLKC_H */
diff --git a/include/dt-bindings/clock/meson8b-clkc.h b/include/dt-bindings/clock/meson8b-clkc.h
new file mode 100644
index 000000000000..bd2720d58e0c
--- /dev/null
+++ b/include/dt-bindings/clock/meson8b-clkc.h
@@ -0,0 +1,25 @@
+/*
+ * Meson8b clock tree IDs
+ */
+
+#ifndef __MESON8B_CLKC_H
+#define __MESON8B_CLKC_H
+
+#define CLKID_UNUSED		0
+#define CLKID_XTAL		1
+#define CLKID_PLL_FIXED		2
+#define CLKID_PLL_VID		3
+#define CLKID_PLL_SYS		4
+#define CLKID_FCLK_DIV2		5
+#define CLKID_FCLK_DIV3		6
+#define CLKID_FCLK_DIV4		7
+#define CLKID_FCLK_DIV5		8
+#define CLKID_FCLK_DIV7		9
+#define CLKID_CLK81		10
+#define CLKID_MALI		11
+#define CLKID_CPUCLK		12
+#define CLKID_ZERO		13
+
+#define CLK_NR_CLKS		(CLKID_ZERO + 1)
+
+#endif /* __MESON8B_CLKC_H */

From 12545fa33ad3363c639ec56bb84c8a58cfbcf65b Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Mon, 1 Jun 2015 13:13:54 +0200
Subject: [PATCH 103/135] clk: meson: Document bindings for Meson8b clock
 controller

Add documentation for  the clock controller.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 .../bindings/clock/amlogic,meson8b-clkc.txt   | 40 +++++++++++++++++++
 1 file changed, 40 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt

diff --git a/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt
new file mode 100644
index 000000000000..2b7b3fa588d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt
@@ -0,0 +1,40 @@
+* Amlogic Meson8b Clock and Reset Unit
+
+The Amlogic Meson8b clock controller generates and supplies clock to various
+controllers within the SoC.
+
+Required Properties:
+
+- compatible: should be "amlogic,meson8b-clkc"
+- reg: it must be composed by two tuples:
+	0) physical base address of the xtal register and length of memory
+	   mapped region.
+	1) physical base address of the clock controller and length of memory
+	   mapped region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/meson8b-clkc.h header and can be
+used in device tree sources.
+
+Example: Clock controller node:
+
+	clkc: clock-controller@c1104000 {
+		#clock-cells = <1>;
+		compatible = "amlogic,meson8b-clkc";
+		reg = <0xc1108000 0x4>, <0xc1104000 0x460>;
+	};
+
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+	uart_AO: serial@c81004c0 {
+		compatible = "amlogic,meson-uart";
+		reg = <0xc81004c0 0x14>;
+		interrupts = <0 90 1>;
+		clocks = <&clkc CLKID_CLK81>;
+		status = "disabled";
+	};

From 28b9fcd016126e6495d486c169fddaf26091a04b Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Mon, 1 Jun 2015 13:13:55 +0200
Subject: [PATCH 104/135] clk: meson8b: Add support for Meson8b clocks

This patch adds support for the basic clocks found on the Amlogic
Meson8b SoCs.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/meson/Makefile       |   1 +
 drivers/clk/meson/meson8b-clkc.c | 196 +++++++++++++++++++++++++++++++
 2 files changed, 197 insertions(+)
 create mode 100644 drivers/clk/meson/meson8b-clkc.c

diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index 66c6d8d23553..6d45531df9ab 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-y += clkc.o clk-pll.o clk-cpu.o
+obj-y += meson8b-clkc.o
diff --git a/drivers/clk/meson/meson8b-clkc.c b/drivers/clk/meson/meson8b-clkc.c
new file mode 100644
index 000000000000..61f6d55c4ac7
--- /dev/null
+++ b/drivers/clk/meson/meson8b-clkc.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <dt-bindings/clock/meson8b-clkc.h>
+
+#include "clkc.h"
+
+#define MESON8B_REG_CTL0_ADDR		0x0000
+#define MESON8B_REG_SYS_CPU_CNTL1	0x015c
+#define MESON8B_REG_HHI_MPEG		0x0174
+#define MESON8B_REG_MALI		0x01b0
+#define MESON8B_REG_PLL_FIXED		0x0280
+#define MESON8B_REG_PLL_SYS		0x0300
+#define MESON8B_REG_PLL_VID		0x0320
+
+static const struct pll_rate_table sys_pll_rate_table[] = {
+	PLL_RATE(312000000, 52, 1, 2),
+	PLL_RATE(336000000, 56, 1, 2),
+	PLL_RATE(360000000, 60, 1, 2),
+	PLL_RATE(384000000, 64, 1, 2),
+	PLL_RATE(408000000, 68, 1, 2),
+	PLL_RATE(432000000, 72, 1, 2),
+	PLL_RATE(456000000, 76, 1, 2),
+	PLL_RATE(480000000, 80, 1, 2),
+	PLL_RATE(504000000, 84, 1, 2),
+	PLL_RATE(528000000, 88, 1, 2),
+	PLL_RATE(552000000, 92, 1, 2),
+	PLL_RATE(576000000, 96, 1, 2),
+	PLL_RATE(600000000, 50, 1, 1),
+	PLL_RATE(624000000, 52, 1, 1),
+	PLL_RATE(648000000, 54, 1, 1),
+	PLL_RATE(672000000, 56, 1, 1),
+	PLL_RATE(696000000, 58, 1, 1),
+	PLL_RATE(720000000, 60, 1, 1),
+	PLL_RATE(744000000, 62, 1, 1),
+	PLL_RATE(768000000, 64, 1, 1),
+	PLL_RATE(792000000, 66, 1, 1),
+	PLL_RATE(816000000, 68, 1, 1),
+	PLL_RATE(840000000, 70, 1, 1),
+	PLL_RATE(864000000, 72, 1, 1),
+	PLL_RATE(888000000, 74, 1, 1),
+	PLL_RATE(912000000, 76, 1, 1),
+	PLL_RATE(936000000, 78, 1, 1),
+	PLL_RATE(960000000, 80, 1, 1),
+	PLL_RATE(984000000, 82, 1, 1),
+	PLL_RATE(1008000000, 84, 1, 1),
+	PLL_RATE(1032000000, 86, 1, 1),
+	PLL_RATE(1056000000, 88, 1, 1),
+	PLL_RATE(1080000000, 90, 1, 1),
+	PLL_RATE(1104000000, 92, 1, 1),
+	PLL_RATE(1128000000, 94, 1, 1),
+	PLL_RATE(1152000000, 96, 1, 1),
+	PLL_RATE(1176000000, 98, 1, 1),
+	PLL_RATE(1200000000, 50, 1, 0),
+	PLL_RATE(1224000000, 51, 1, 0),
+	PLL_RATE(1248000000, 52, 1, 0),
+	PLL_RATE(1272000000, 53, 1, 0),
+	PLL_RATE(1296000000, 54, 1, 0),
+	PLL_RATE(1320000000, 55, 1, 0),
+	PLL_RATE(1344000000, 56, 1, 0),
+	PLL_RATE(1368000000, 57, 1, 0),
+	PLL_RATE(1392000000, 58, 1, 0),
+	PLL_RATE(1416000000, 59, 1, 0),
+	PLL_RATE(1440000000, 60, 1, 0),
+	PLL_RATE(1464000000, 61, 1, 0),
+	PLL_RATE(1488000000, 62, 1, 0),
+	PLL_RATE(1512000000, 63, 1, 0),
+	PLL_RATE(1536000000, 64, 1, 0),
+	{ /* sentinel */ },
+};
+
+static const struct clk_div_table cpu_div_table[] = {
+	{ .val = 1, .div = 1 },
+	{ .val = 2, .div = 2 },
+	{ .val = 3, .div = 3 },
+	{ .val = 2, .div = 4 },
+	{ .val = 3, .div = 6 },
+	{ .val = 4, .div = 8 },
+	{ .val = 5, .div = 10 },
+	{ .val = 6, .div = 12 },
+	{ .val = 7, .div = 14 },
+	{ .val = 8, .div = 16 },
+	{ /* sentinel */ },
+};
+
+PNAME(p_xtal)		= { "xtal" };
+PNAME(p_fclk_div)	= { "fixed_pll" };
+PNAME(p_cpu_clk)	= { "sys_pll" };
+PNAME(p_clk81)		= { "fclk_div3", "fclk_div4", "fclk_div5" };
+PNAME(p_mali)		= { "fclk_div3", "fclk_div4", "fclk_div5",
+			    "fclk_div7", "zero" };
+
+static u32 mux_table_clk81[]	= { 6, 5, 7 };
+static u32 mux_table_mali[]	= { 6, 5, 7, 4, 0 };
+
+static struct pll_conf pll_confs = {
+	.m		= PARM(0x00, 0,  9),
+	.n		= PARM(0x00, 9,  5),
+	.od		= PARM(0x00, 16, 2),
+};
+
+static struct pll_conf sys_pll_conf = {
+	.m		= PARM(0x00, 0,  9),
+	.n		= PARM(0x00, 9,  5),
+	.od		= PARM(0x00, 16, 2),
+	.rate_table	= sys_pll_rate_table,
+};
+
+static const struct composite_conf clk81_conf __initconst = {
+	.mux_table		= mux_table_clk81,
+	.mux_flags		= CLK_MUX_READ_ONLY,
+	.mux_parm		= PARM(0x00, 12, 3),
+	.div_parm		= PARM(0x00, 0, 7),
+	.gate_parm		= PARM(0x00, 7, 1),
+};
+
+static const struct composite_conf mali_conf __initconst = {
+	.mux_table		= mux_table_mali,
+	.mux_parm		= PARM(0x00, 9, 3),
+	.div_parm		= PARM(0x00, 0, 7),
+	.gate_parm		= PARM(0x00, 8, 1),
+};
+
+static const struct clk_conf meson8b_xtal_conf __initconst =
+	FIXED_RATE_P(MESON8B_REG_CTL0_ADDR, CLKID_XTAL, "xtal",
+		     CLK_IS_ROOT, PARM(0x00, 4, 7));
+
+static const struct clk_conf meson8b_clk_confs[] __initconst = {
+	FIXED_RATE(CLKID_ZERO, "zero", CLK_IS_ROOT, 0),
+	PLL(MESON8B_REG_PLL_FIXED, CLKID_PLL_FIXED, "fixed_pll",
+	    p_xtal, 0, &pll_confs),
+	PLL(MESON8B_REG_PLL_VID, CLKID_PLL_VID, "vid_pll",
+	    p_xtal, 0, &pll_confs),
+	PLL(MESON8B_REG_PLL_SYS, CLKID_PLL_SYS, "sys_pll",
+	    p_xtal, 0, &sys_pll_conf),
+	FIXED_FACTOR_DIV(CLKID_FCLK_DIV2, "fclk_div2", p_fclk_div, 0, 2),
+	FIXED_FACTOR_DIV(CLKID_FCLK_DIV3, "fclk_div3", p_fclk_div, 0, 3),
+	FIXED_FACTOR_DIV(CLKID_FCLK_DIV4, "fclk_div4", p_fclk_div, 0, 4),
+	FIXED_FACTOR_DIV(CLKID_FCLK_DIV5, "fclk_div5", p_fclk_div, 0, 5),
+	FIXED_FACTOR_DIV(CLKID_FCLK_DIV7, "fclk_div7", p_fclk_div, 0, 7),
+	CPU(MESON8B_REG_SYS_CPU_CNTL1, CLKID_CPUCLK, "a5_clk", p_cpu_clk,
+	    cpu_div_table),
+	COMPOSITE(MESON8B_REG_HHI_MPEG, CLKID_CLK81, "clk81", p_clk81,
+		  CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED, &clk81_conf),
+	COMPOSITE(MESON8B_REG_MALI, CLKID_MALI, "mali", p_mali,
+		  CLK_IGNORE_UNUSED, &mali_conf),
+};
+
+static void __init meson8b_clkc_init(struct device_node *np)
+{
+	void __iomem *clk_base;
+
+	if (!meson_clk_init(np, CLK_NR_CLKS))
+		return;
+
+	/* XTAL */
+	clk_base = of_iomap(np, 0);
+	if (!clk_base) {
+		pr_err("%s: Unable to map xtal base\n", __func__);
+		return;
+	}
+
+	meson_clk_register_clks(&meson8b_xtal_conf, 1, clk_base);
+	iounmap(clk_base);
+
+	/*  Generic clocks and PLLs */
+	clk_base = of_iomap(np, 1);
+	if (!clk_base) {
+		pr_err("%s: Unable to map clk base\n", __func__);
+		return;
+	}
+
+	meson_clk_register_clks(meson8b_clk_confs,
+				ARRAY_SIZE(meson8b_clk_confs),
+				clk_base);
+}
+CLK_OF_DECLARE(meson8b_clock, "amlogic,meson8b-clkc", meson8b_clkc_init);

From 2e61dfb3602b904966491f260f62c01b9895936a Mon Sep 17 00:00:00 2001
From: Dinh Nguyen <dinguyen@opensource.altera.com>
Date: Fri, 5 Jun 2015 11:26:13 -0500
Subject: [PATCH 105/135] clk: of: helper for filling parent clock array and
 return num of parents

Sprinkled all through the platform clock drivers are code like this to
fill the clock parent array:

for (i = 0; i < num_parents; ++i)
	parent_names[i] = of_clk_get_parent_name(np, i);

The of_clk_parent_fill() will do the same as the code above, and while
at it, return the number of parents as well since the logic of the
function is to the walk the clock node to look for the parent.

Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
[sboyd@codeaurora.org: Fixed kernel-doc]
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c            | 21 +++++++++++++++++++++
 include/linux/clk-provider.h |  2 ++
 2 files changed, 23 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a522dbbc01b9..ee222e28bd97 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -3016,6 +3016,27 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
 }
 EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
 
+/**
+ * of_clk_parent_fill() - Fill @parents with names of @np's parents and return
+ * number of parents
+ * @np: Device node pointer associated with clock provider
+ * @parents: pointer to char array that hold the parents' names
+ * @size: size of the @parents array
+ *
+ * Return: number of parents for the clock node.
+ */
+int of_clk_parent_fill(struct device_node *np, const char **parents,
+		       unsigned int size)
+{
+	unsigned int i = 0;
+
+	while (i < size && (parents[i] = of_clk_get_parent_name(np, i)) != NULL)
+		i++;
+
+	return i;
+}
+EXPORT_SYMBOL_GPL(of_clk_parent_fill);
+
 struct clock_provider {
 	of_clk_init_cb_t clk_init_cb;
 	struct device_node *np;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 5378c2aba4d2..2e5df069ca34 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -626,6 +626,8 @@ struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
 				  void *data);
 struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
 int of_clk_get_parent_count(struct device_node *np);
+int of_clk_parent_fill(struct device_node *np, const char **parents,
+		       unsigned int size);
 const char *of_clk_get_parent_name(struct device_node *np, int index);
 
 void of_clk_init(const struct of_device_id *matches);

From 761d3e328c503c8428cec54e33196e49f5c46e55 Mon Sep 17 00:00:00 2001
From: Dinh Nguyen <dinguyen@opensource.altera.com>
Date: Fri, 5 Jun 2015 11:26:14 -0500
Subject: [PATCH 106/135] clk: socfpga: make use of of_clk_parent_fill helper
 function

Use of_clk_parent_fill to fill in the parent clock's array.

Signed-off-by: Dinh Nguyen <dinguyen@opensource.altera.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/socfpga/clk-gate.c | 6 +-----
 drivers/clk/socfpga/clk-pll.c  | 7 +------
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c
index 0add360525a0..82449cd76fd7 100644
--- a/drivers/clk/socfpga/clk-gate.c
+++ b/drivers/clk/socfpga/clk-gate.c
@@ -190,7 +190,6 @@ static void __init __socfpga_gate_init(struct device_node *node,
 	const char *parent_name[SOCFPGA_MAX_PARENTS];
 	struct clk_init_data init;
 	int rc;
-	int i = 0;
 
 	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
 	if (WARN_ON(!socfpga_clk))
@@ -234,12 +233,9 @@ static void __init __socfpga_gate_init(struct device_node *node,
 	init.name = clk_name;
 	init.ops = ops;
 	init.flags = 0;
-	while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] =
-			of_clk_get_parent_name(node, i)) != NULL)
-		i++;
 
+	init.num_parents = of_clk_parent_fill(node, parent_name, SOCFPGA_MAX_PARENTS);
 	init.parent_names = parent_name;
-	init.num_parents = i;
 	socfpga_clk->hw.hw.init = &init;
 
 	clk = clk_register(NULL, &socfpga_clk->hw.hw);
diff --git a/drivers/clk/socfpga/clk-pll.c b/drivers/clk/socfpga/clk-pll.c
index de6da957a09d..8f26b5234947 100644
--- a/drivers/clk/socfpga/clk-pll.c
+++ b/drivers/clk/socfpga/clk-pll.c
@@ -92,7 +92,6 @@ static __init struct clk *__socfpga_pll_init(struct device_node *node,
 	struct clk_init_data init;
 	struct device_node *clkmgr_np;
 	int rc;
-	int i = 0;
 
 	of_property_read_u32(node, "reg", &reg);
 
@@ -111,11 +110,7 @@ static __init struct clk *__socfpga_pll_init(struct device_node *node,
 	init.ops = ops;
 	init.flags = 0;
 
-	while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] =
-			of_clk_get_parent_name(node, i)) != NULL)
-		i++;
-
-	init.num_parents = i;
+	init.num_parents = of_clk_parent_fill(node, parent_name, SOCFPGA_MAX_PARENTS);
 	init.parent_names = parent_name;
 	pll_clk->hw.hw.init = &init;
 

From f7c172b5c11ff91ce103aa94a284fcf635554df0 Mon Sep 17 00:00:00 2001
From: Chanwoo Choi <cw00.choi@samsung.com>
Date: Mon, 27 Apr 2015 20:36:33 +0900
Subject: [PATCH 107/135] clk: exynos5433: Add CLK_SET_RATE_PARENT to support
 DVFS for big.LITTLE core

This patch adds CLK_SET_RATE_PARENT flag to support DVFS of Cortex-{A53|A57}
core (big.LITTLE core) because 'sclk_{apollo|atlas}' leaf clock is used to
change the CPU frequency of Cortex-{A53|A57} core in arm_big_little.c driver.
- 'apollo' word means the LITTLE core (Cortex-A53 core) in Exynos5433 TRM.
- 'atlas' word means the big core (Cortex-A57 core) in Exynos5433 TRM.

Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/clk/samsung/clk-exynos5433.c | 26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index 9e04ae2bb4d7..e4a67717d9a9 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -3582,7 +3582,7 @@ static struct samsung_pll_clock apollo_pll_clks[] __initdata = {
 static struct samsung_mux_clock apollo_mux_clks[] __initdata = {
 	/* MUX_SEL_APOLLO0 */
 	MUX_F(CLK_MOUT_APOLLO_PLL, "mout_apollo_pll", mout_apollo_pll_p,
-			MUX_SEL_APOLLO0, 0, 1, 0, CLK_MUX_READ_ONLY),
+			MUX_SEL_APOLLO0, 0, 1, CLK_SET_RATE_PARENT, 0),
 
 	/* MUX_SEL_APOLLO1 */
 	MUX(CLK_MOUT_BUS_PLL_APOLLO_USER, "mout_bus_pll_apollo_user",
@@ -3590,7 +3590,7 @@ static struct samsung_mux_clock apollo_mux_clks[] __initdata = {
 
 	/* MUX_SEL_APOLLO2 */
 	MUX_F(CLK_MOUT_APOLLO, "mout_apollo", mout_apollo_p, MUX_SEL_APOLLO2,
-			0, 1, 0, CLK_MUX_READ_ONLY),
+			0, 1, CLK_SET_RATE_PARENT, 0),
 };
 
 static struct samsung_div_clock apollo_div_clks[] __initdata = {
@@ -3611,11 +3611,9 @@ static struct samsung_div_clock apollo_div_clks[] __initdata = {
 			DIV_APOLLO0, 8, 3, CLK_GET_RATE_NOCACHE,
 			CLK_DIVIDER_READ_ONLY),
 	DIV_F(CLK_DIV_APOLLO2, "div_apollo2", "div_apollo1",
-			DIV_APOLLO0, 4, 3, CLK_GET_RATE_NOCACHE,
-			CLK_DIVIDER_READ_ONLY),
+			DIV_APOLLO0, 4, 3, CLK_SET_RATE_PARENT, 0),
 	DIV_F(CLK_DIV_APOLLO1, "div_apollo1", "mout_apollo",
-			DIV_APOLLO0, 0, 3, CLK_GET_RATE_NOCACHE,
-			CLK_DIVIDER_READ_ONLY),
+			DIV_APOLLO0, 0, 3, CLK_SET_RATE_PARENT, 0),
 
 	/* DIV_APOLLO1 */
 	DIV_F(CLK_DIV_SCLK_HPM_APOLLO, "div_sclk_hpm_apollo", "mout_apollo",
@@ -3666,7 +3664,8 @@ static struct samsung_gate_clock apollo_gate_clks[] __initdata = {
 	GATE(CLK_SCLK_HPM_APOLLO, "sclk_hpm_apollo", "div_sclk_hpm_apollo",
 			ENABLE_SCLK_APOLLO, 1, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_SCLK_APOLLO, "sclk_apollo", "div_apollo2",
-			ENABLE_SCLK_APOLLO, 0, CLK_IGNORE_UNUSED, 0),
+			ENABLE_SCLK_APOLLO, 0,
+			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 };
 
 static struct samsung_cmu_info apollo_cmu_info __initdata = {
@@ -3775,7 +3774,7 @@ static struct samsung_pll_clock atlas_pll_clks[] __initdata = {
 static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
 	/* MUX_SEL_ATLAS0 */
 	MUX_F(CLK_MOUT_ATLAS_PLL, "mout_atlas_pll", mout_atlas_pll_p,
-			MUX_SEL_ATLAS0, 0, 1, 0, CLK_MUX_READ_ONLY),
+			MUX_SEL_ATLAS0, 0, 1, CLK_SET_RATE_PARENT, 0),
 
 	/* MUX_SEL_ATLAS1 */
 	MUX(CLK_MOUT_BUS_PLL_ATLAS_USER, "mout_bus_pll_atlas_user",
@@ -3783,7 +3782,7 @@ static struct samsung_mux_clock atlas_mux_clks[] __initdata = {
 
 	/* MUX_SEL_ATLAS2 */
 	MUX_F(CLK_MOUT_ATLAS, "mout_atlas", mout_atlas_p, MUX_SEL_ATLAS2,
-			0, 1, 0, CLK_MUX_READ_ONLY),
+			0, 1, CLK_SET_RATE_PARENT, 0),
 };
 
 static struct samsung_div_clock atlas_div_clks[] __initdata = {
@@ -3804,11 +3803,9 @@ static struct samsung_div_clock atlas_div_clks[] __initdata = {
 			DIV_ATLAS0, 8, 3, CLK_GET_RATE_NOCACHE,
 			CLK_DIVIDER_READ_ONLY),
 	DIV_F(CLK_DIV_ATLAS2, "div_atlas2", "div_atlas1",
-			DIV_ATLAS0, 4, 3, CLK_GET_RATE_NOCACHE,
-			CLK_DIVIDER_READ_ONLY),
+			DIV_ATLAS0, 4, 3, CLK_SET_RATE_PARENT, 0),
 	DIV_F(CLK_DIV_ATLAS1, "div_atlas1", "mout_atlas",
-			DIV_ATLAS0, 0, 3, CLK_GET_RATE_NOCACHE,
-			CLK_DIVIDER_READ_ONLY),
+			DIV_ATLAS0, 0, 3, CLK_SET_RATE_PARENT, 0),
 
 	/* DIV_ATLAS1 */
 	DIV_F(CLK_DIV_SCLK_HPM_ATLAS, "div_sclk_hpm_atlas", "mout_atlas",
@@ -3885,7 +3882,8 @@ static struct samsung_gate_clock atlas_gate_clks[] __initdata = {
 	GATE(CLK_ATCLK, "atclk", "div_atclk_atlas",
 			ENABLE_SCLK_ATLAS, 1, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_SCLK_ATLAS, "sclk_atlas", "div_atlas2",
-			ENABLE_SCLK_ATLAS, 0, CLK_IGNORE_UNUSED, 0),
+			ENABLE_SCLK_ATLAS, 0,
+			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 };
 
 static struct samsung_cmu_info atlas_cmu_info __initdata = {

From 2a9c67b2d3eb81b26493b5d2ee9d27eb4a806c53 Mon Sep 17 00:00:00 2001
From: Hyungwon Hwang <human.hwang@samsung.com>
Date: Mon, 27 Apr 2015 20:36:34 +0900
Subject: [PATCH 108/135] clk: exynos5433: Add DIV_CPIF to the list of stored
 registers on suspend

This DIV_CPIF register must be stored when the system is suspended, and must
be restored on system resume. This patch adds the register to the list of
restored registers.

Signed-off-by: Hyungwon Hwang <human.hwang@samsung.com>
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/clk/samsung/clk-exynos5433.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index e4a67717d9a9..5d8b4a82c98b 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -835,6 +835,7 @@ static unsigned long cpif_clk_regs[] __initdata = {
 	MPHY_PLL_CON1,
 	MPHY_PLL_FREQ_DET,
 	MUX_SEL_CPIF0,
+	DIV_CPIF,
 	ENABLE_SCLK_CPIF,
 };
 

From eceb7aaec07d17a0facb4236c27f7d331c3cdf46 Mon Sep 17 00:00:00 2001
From: Joonyoung Shim <jy0922.shim@samsung.com>
Date: Mon, 27 Apr 2015 20:36:35 +0900
Subject: [PATCH 109/135] clk: exynos5433: Add clock flag to support the DVFS
 of GPU

This patch adds the CLK_SET_RATE_PARENT flag for 'aclk_g3d' clock and parent
clocks becuase 'aclk_g3d' is used to change GPU frequency for DVFS (Dynamic
Voltage Frequency Scaling) feature and adds CLK_IGNORE_UNUSED flags to
'aclk_asyncapbs_g3d'/'aclk_asyncapbm_g3d' clocks to access the SFR
of the MALI device.

Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>
[cw00.choi: Add patch description and add CLK_SET_RATE_PARENT to 'aclk_g3d' clk]
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/clk/samsung/clk-exynos5433.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index 5d8b4a82c98b..256fec0f2d18 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -3287,10 +3287,10 @@ static struct samsung_pll_clock g3d_pll_clks[] __initdata = {
 
 static struct samsung_mux_clock g3d_mux_clks[] __initdata = {
 	/* MUX_SEL_G3D */
-	MUX(CLK_MOUT_ACLK_G3D_400, "mout_aclk_g3d_400", mout_aclk_g3d_400_p,
-			MUX_SEL_G3D, 8, 1),
-	MUX(CLK_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
-			MUX_SEL_G3D, 0, 1),
+	MUX_F(CLK_MOUT_ACLK_G3D_400, "mout_aclk_g3d_400", mout_aclk_g3d_400_p,
+			MUX_SEL_G3D, 8, 1, CLK_SET_RATE_PARENT, 0),
+	MUX_F(CLK_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p,
+			MUX_SEL_G3D, 0, 1, CLK_SET_RATE_PARENT, 0),
 };
 
 static struct samsung_div_clock g3d_div_clks[] __initdata = {
@@ -3299,8 +3299,8 @@ static struct samsung_div_clock g3d_div_clks[] __initdata = {
 			8, 2),
 	DIV(CLK_DIV_PCLK_G3D, "div_pclk_g3d", "div_aclk_g3d", DIV_G3D,
 			4, 3),
-	DIV(CLK_DIV_ACLK_G3D, "div_aclk_g3d", "mout_aclk_g3d_400", DIV_G3D,
-			0, 3),
+	DIV_F(CLK_DIV_ACLK_G3D, "div_aclk_g3d", "mout_aclk_g3d_400", DIV_G3D,
+			0, 3, CLK_SET_RATE_PARENT, 0),
 };
 
 static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
@@ -3310,9 +3310,9 @@ static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
 	GATE(CLK_ACLK_BTS_G3D0, "aclk_bts_g3d0", "div_aclk_g3d",
 			ENABLE_ACLK_G3D, 6, 0, 0),
 	GATE(CLK_ACLK_ASYNCAPBS_G3D, "aclk_asyncapbs_g3d", "div_pclk_g3d",
-			ENABLE_ACLK_G3D, 5, 0, 0),
+			ENABLE_ACLK_G3D, 5, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_ASYNCAPBM_G3D, "aclk_asyncapbm_g3d", "div_aclk_g3d",
-			ENABLE_ACLK_G3D, 4, 0, 0),
+			ENABLE_ACLK_G3D, 4, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_AHB2APB_G3DP, "aclk_ahb2apb_g3dp", "div_pclk_g3d",
 			ENABLE_ACLK_G3D, 3, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_G3DNP_150, "aclk_g3dnp_150", "div_pclk_g3d",
@@ -3320,7 +3320,7 @@ static struct samsung_gate_clock g3d_gate_clks[] __initdata = {
 	GATE(CLK_ACLK_G3DND_600, "aclk_g3dnd_600", "div_aclk_g3d",
 			ENABLE_ACLK_G3D, 1, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_G3D, "aclk_g3d", "div_aclk_g3d",
-			ENABLE_ACLK_G3D, 0, 0, 0),
+			ENABLE_ACLK_G3D, 0, CLK_SET_RATE_PARENT, 0),
 
 	/* ENABLE_PCLK_G3D */
 	GATE(CLK_PCLK_BTS_G3D1, "pclk_bts_g3d1", "div_pclk_g3d",

From 80e7264c8f1b9b2ca73bc8db327fb3b73e626b7b Mon Sep 17 00:00:00 2001
From: Jonghwa Lee <jonghwa3.lee@samsung.com>
Date: Mon, 27 Apr 2015 20:36:36 +0900
Subject: [PATCH 110/135] clk: exynos5433: Add CLK_IGNORE_UNUSED flag to clocks
 for SMC

This patch adds 'CLK_IGNORE_UNUSED' flag to clocks which is required for
operation of secure monitor call (smc). System will hang when it executes 'smc'
with one of those clock is gated. All related clocks must be enabled.

Signed-off-by: Jonghwa Lee <jonghwa3.lee@samsung.com>
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 drivers/clk/samsung/clk-exynos5433.c | 36 ++++++++++++++--------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index 256fec0f2d18..39c95649d3d0 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -1390,7 +1390,7 @@ static struct samsung_gate_clock mif_gate_clks[] __initdata = {
 
 	/* ENABLE_ACLK_MIF2 */
 	GATE(CLK_ACLK_MIFND_266, "aclk_mifnd_266", "div_aclk_mif_266",
-			ENABLE_ACLK_MIF2, 20, 0, 0),
+			ENABLE_ACLK_MIF2, 20, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_PPMU_DREX1S3, "aclk_ppmu_drex1s3", "div_aclk_drex1",
 			ENABLE_ACLK_MIF2, 17, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_PPMU_DREX1S1, "aclk_ppmu_drex1s1", "div_aclk_drex1",
@@ -1833,39 +1833,39 @@ static struct samsung_gate_clock peris_gate_clks[] __initdata = {
 
 	/* ENABLE_PCLK_PERIS_SECURE_TZPC */
 	GATE(CLK_PCLK_TZPC12, "pclk_tzpc12", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 12, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 12, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC11, "pclk_tzpc11", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 11, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 11, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC10, "pclk_tzpc10", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 10, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 10, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC9, "pclk_tzpc9", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 9, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 9, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC8, "pclk_tzpc8", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 8, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 8, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC7, "pclk_tzpc7", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 7, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 7, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC6, "pclk_tzpc6", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 6, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 6, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC5, "pclk_tzpc5", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 5, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 5, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC4, "pclk_tzpc4", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 4, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 4, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC3, "pclk_tzpc3", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 3, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 3, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC2, "pclk_tzpc2", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 2, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 2, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC1, "pclk_tzpc1", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 1, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 1, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_PCLK_TZPC0, "pclk_tzpc0", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_TZPC, 0, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_TZPC, 0, CLK_IGNORE_UNUSED, 0),
 
 	/* ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF */
 	GATE(CLK_PCLK_SECKEY_APBIF, "pclk_seckey_apbif", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF, 0, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_SECKEY_APBIF, 0, CLK_IGNORE_UNUSED, 0),
 
 	/* ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF */
 	GATE(CLK_PCLK_CHIPID_APBIF, "pclk_chipid_apbif", "aclk_peris_66",
-			ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF, 0, 0, 0),
+			ENABLE_PCLK_PERIS_SECURE_CHIPID_APBIF, 0, CLK_IGNORE_UNUSED, 0),
 
 	/* ENABLE_PCLK_PERIS_SECURE_TOPRTC */
 	GATE(CLK_PCLK_TOPRTC, "pclk_toprtc", "aclk_peris_66",
@@ -1896,11 +1896,11 @@ static struct samsung_gate_clock peris_gate_clks[] __initdata = {
 
 	/* ENABLE_SCLK_PERIS_SECURE_SECKEY */
 	GATE(CLK_SCLK_SECKEY, "sclk_seckey", "oscclk_efuse_common",
-			ENABLE_SCLK_PERIS_SECURE_SECKEY, 0, 0, 0),
+			ENABLE_SCLK_PERIS_SECURE_SECKEY, 0, CLK_IGNORE_UNUSED, 0),
 
 	/* ENABLE_SCLK_PERIS_SECURE_CHIPID */
 	GATE(CLK_SCLK_CHIPID, "sclk_chipid", "oscclk_efuse_common",
-			ENABLE_SCLK_PERIS_SECURE_CHIPID, 0, 0, 0),
+			ENABLE_SCLK_PERIS_SECURE_CHIPID, 0, CLK_IGNORE_UNUSED, 0),
 
 	/* ENABLE_SCLK_PERIS_SECURE_TOPRTC */
 	GATE(CLK_SCLK_TOPRTC, "sclk_toprtc", "oscclk_efuse_common",

From 7eaf8b9f0b699732bab739ae47d4cad55e7ee4e3 Mon Sep 17 00:00:00 2001
From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Wed, 27 May 2015 11:26:27 +0300
Subject: [PATCH 111/135] clk: socfpga: remove a stray tab

This line was indented too far.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Acked-by: Dinh Nguyen <dinguyen@opensource.altera.com>
Signed-off-by: Michael Turquette <mturquette@linaro.org>
---
 drivers/clk/socfpga/clk-gate-a10.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/socfpga/clk-gate-a10.c b/drivers/clk/socfpga/clk-gate-a10.c
index be3e998b85d0..83c6780ff4b2 100644
--- a/drivers/clk/socfpga/clk-gate-a10.c
+++ b/drivers/clk/socfpga/clk-gate-a10.c
@@ -39,7 +39,7 @@ static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
 	else if (socfpgaclk->div_reg) {
 		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
 		val &= div_mask(socfpgaclk->width);
-			div = (1 << val);
+		div = (1 << val);
 	}
 
 	return parent_rate / div;

From b41c7bfa27f221a567e33b44aa5395adfe042229 Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Wed, 10 Jun 2015 14:14:28 -0700
Subject: [PATCH 112/135] clk: cdce925: Fix printk size_t warning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

drivers/clk/clk-cdce925.c:550: warning: format ‘%u’ expects type
‘unsigned int’, but argument 6 has type ‘size_t’

Cc: Mike Looijmans <mike.looijmans@topic.nl>
Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-cdce925.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c
index 56b870d331a1..85fafb41e6ca 100644
--- a/drivers/clk/clk-cdce925.c
+++ b/drivers/clk/clk-cdce925.c
@@ -547,7 +547,7 @@ static int cdce925_regmap_i2c_read(void *context,
 
 	ret = i2c_transfer(i2c->adapter, xfer, 2);
 	if (likely(ret == 2)) {
-		dev_dbg(&i2c->dev, "%s(%zu, %u) %#x %#x\n", __func__,
+		dev_dbg(&i2c->dev, "%s(%zu, %zu) %#x %#x\n", __func__,
 				reg_size, val_size, reg_data[0], *((u8 *)val));
 		return 0;
 	} else if (ret < 0)

From 3037e9ea780027d41baaaabb68a749e49e7c8260 Mon Sep 17 00:00:00 2001
From: Daniel Thompson <daniel.thompson@linaro.org>
Date: Wed, 10 Jun 2015 21:04:54 +0100
Subject: [PATCH 113/135] clk: fixed: Add comment to clk_fixed_set_rate

Currently it is not made explicit why clk_fixed_set_rate() can ignore
its arguments and unconditionally return success. Add a comment
to explain this.

We also mark the clk_ops table const since it should never be
modified at runtime.

Suggested-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk-fixed-factor.c | 8 +++++++-
 include/linux/clk-provider.h   | 2 +-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index e186db263d5e..fccabe497f6e 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -55,10 +55,16 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate,
 static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate,
 				unsigned long parent_rate)
 {
+	/*
+	 * We must report success but we can do so unconditionally because
+	 * clk_factor_round_rate returns values that ensure this call is a
+	 * nop.
+	 */
+
 	return 0;
 }
 
-struct clk_ops clk_fixed_factor_ops = {
+const struct clk_ops clk_fixed_factor_ops = {
 	.round_rate = clk_factor_round_rate,
 	.set_rate = clk_factor_set_rate,
 	.recalc_rate = clk_factor_recalc_rate,
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 2e5df069ca34..4a943d13625b 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -459,7 +459,7 @@ struct clk_fixed_factor {
 	unsigned int	div;
 };
 
-extern struct clk_ops clk_fixed_factor_ops;
+extern const struct clk_ops clk_fixed_factor_ops;
 struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		unsigned int mult, unsigned int div);

From 8c9a8a8f71f43e56d35524fa17646ce45c2f7fe6 Mon Sep 17 00:00:00 2001
From: Maxime Coquelin <maxime.coquelin@st.com>
Date: Wed, 10 Jun 2015 13:28:27 +0200
Subject: [PATCH 114/135] clk: Move debug_node field under DEBUG_FS flag in
 struct clk_core

The debug_node field is only used when DEBUG_FS config is selected,
so declare it only if DEBUG_FS is selected.

Signed-off-by: Maxime Coquelin <maxime.coquelin@st.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index ee222e28bd97..1cf479b9f3b4 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -62,11 +62,11 @@ struct clk_core {
 	int			phase;
 	struct hlist_head	children;
 	struct hlist_node	child_node;
-	struct hlist_node	debug_node;
 	struct hlist_head	clks;
 	unsigned int		notifier_count;
 #ifdef CONFIG_DEBUG_FS
 	struct dentry		*dentry;
+	struct hlist_node	debug_node;
 #endif
 	struct kref		ref;
 };

From 22109785163310666cf9913bafbcc11c5aebe68a Mon Sep 17 00:00:00 2001
From: Stephen Boyd <sboyd@codeaurora.org>
Date: Thu, 11 Jun 2015 16:08:51 -0700
Subject: [PATCH 115/135] clk: pxa: Fix const discarding warning
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

A recent change to mark parent names as const missed this struct
member so we get warnings like:

drivers/clk/pxa/clk-pxa25x.c:122:2: warning: initialization
discards 'const' qualifier from pointer target type

Fix it.

Reported-by: kbuild test robot <fengguang.wu@intel.com>
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/pxa/clk-pxa.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/pxa/clk-pxa.h b/drivers/clk/pxa/clk-pxa.h
index 7bf532dca709..d1de805df867 100644
--- a/drivers/clk/pxa/clk-pxa.h
+++ b/drivers/clk/pxa/clk-pxa.h
@@ -72,7 +72,7 @@ struct desc_clk_cken {
 	const char *name;
 	const char *dev_id;
 	const char *con_id;
-	const char **parent_names;
+	const char * const *parent_names;
 	struct clk_fixed_factor lp;
 	struct clk_fixed_factor hp;
 	struct clk_gate gate;

From 46965688acd0f9599a3c3ecce82109b3b24153a9 Mon Sep 17 00:00:00 2001
From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Thu, 11 Jun 2015 18:20:46 +0300
Subject: [PATCH 116/135] clk: meson: add some error handling in
 meson_clk_register_cpu()

This error handling hopefully isn't needed but it make the static
checkers happy.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Acked-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/meson/clk-cpu.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/meson/clk-cpu.c b/drivers/clk/meson/clk-cpu.c
index 148e99fc5970..71ad493b94df 100644
--- a/drivers/clk/meson/clk-cpu.c
+++ b/drivers/clk/meson/clk-cpu.c
@@ -213,22 +213,30 @@ struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf,
 	if (!pclk) {
 		pr_err("%s: could not lookup parent clock %s\n",
 				__func__, clk_conf->clks_parent[0]);
-		return ERR_PTR(-EINVAL);
+		ret = -EINVAL;
+		goto free_clk;
 	}
 
 	ret = clk_notifier_register(pclk, &clk_cpu->clk_nb);
 	if (ret) {
 		pr_err("%s: failed to register clock notifier for %s\n",
 				__func__, clk_conf->clk_name);
-		return ERR_PTR(-EINVAL);
+		goto free_clk;
 	}
 
 	clk = clk_register(NULL, &clk_cpu->hw);
 	if (IS_ERR(clk)) {
-		clk_notifier_unregister(pclk, &clk_cpu->clk_nb);
-		kfree(clk_cpu);
+		ret = PTR_ERR(clk);
+		goto unregister_clk_nb;
 	}
 
 	return clk;
+
+unregister_clk_nb:
+	clk_notifier_unregister(pclk, &clk_cpu->clk_nb);
+free_clk:
+	kfree(clk_cpu);
+
+	return ERR_PTR(ret);
 }
 

From a85fa007b772611fc97f3d68bce33e69a5ed8945 Mon Sep 17 00:00:00 2001
From: Michael Turquette <mturquette@baylibre.com>
Date: Wed, 17 Jun 2015 13:41:04 -0700
Subject: [PATCH 117/135] MAINTAINERS: update email for Michael Turquette

Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index d8afd2953678..15b6d710d222 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2642,7 +2642,7 @@ F:	Documentation/devicetree/bindings/media/coda.txt
 F:	drivers/media/platform/coda/
 
 COMMON CLK FRAMEWORK
-M:	Mike Turquette <mturquette@linaro.org>
+M:	Michael Turquette <mturquette@baylibre.com>
 M:	Stephen Boyd <sboyd@codeaurora.org>
 L:	linux-clk@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git

From 476276d69d84edd4f5de9711f55c810dfc69c26c Mon Sep 17 00:00:00 2001
From: Ray Jui <rjui@broadcom.com>
Date: Tue, 5 May 2015 11:13:18 -0700
Subject: [PATCH 118/135] clk: iproc: define Broadcom iProc clock binding

Document the device tree binding for Broadcom iProc architecture based
clock controller

Signed-off-by: Ray Jui <rjui@broadcom.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 .../bindings/clock/brcm,iproc-clocks.txt      | 132 ++++++++++++++++++
 1 file changed, 132 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt

diff --git a/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt b/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt
new file mode 100644
index 000000000000..da8d9bb5751c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt
@@ -0,0 +1,132 @@
+Broadcom iProc Family Clocks
+
+This binding uses the common clock binding:
+    Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The iProc clock controller manages clocks that are common to the iProc family.
+An SoC from the iProc family may have several PPLs, e.g., ARMPLL, GENPLL,
+LCPLL0, MIPIPLL, and etc., all derived from an onboard crystal. Each PLL
+comprises of several leaf clocks
+
+Required properties for a PLL and its leaf clocks:
+
+- compatible:
+    Should have a value of the form "brcm,<soc>-<pll>". For example, GENPLL on
+Cygnus has a compatible string of "brcm,cygnus-genpll"
+
+- #clock-cells:
+    Have a value of <1> since there are more than 1 leaf clock of a given PLL
+
+- reg:
+    Define the base and range of the I/O address space that contain the iProc
+clock control registers required for the PLL
+
+- clocks:
+    The input parent clock phandle for the PLL. For most iProc PLLs, this is an
+onboard crystal with a fixed rate
+
+- clock-output-names:
+    An ordered list of strings defining the names of the clocks
+
+Example:
+
+	osc: oscillator {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <25000000>;
+	};
+
+	genpll: genpll {
+		#clock-cells = <1>;
+		compatible = "brcm,cygnus-genpll";
+		reg = <0x0301d000 0x2c>, <0x0301c020 0x4>;
+		clocks = <&osc>;
+		clock-output-names = "genpll", "axi21", "250mhz", "ihost_sys",
+				     "enet_sw", "audio_125", "can";
+	};
+
+Required properties for ASIU clocks:
+
+ASIU clocks are a special case. These clocks are derived directly from the
+reference clock of the onboard crystal
+
+- compatible:
+    Should have a value of the form "brcm,<soc>-asiu-clk". For example, ASIU
+clocks for Cygnus have a compatible string of "brcm,cygnus-asiu-clk"
+
+- #clock-cells:
+    Have a value of <1> since there are more than 1 ASIU clocks
+
+- reg:
+    Define the base and range of the I/O address space that contain the iProc
+clock control registers required for ASIU clocks
+
+- clocks:
+    The input parent clock phandle for the ASIU clock, i.e., the onboard
+crystal
+
+- clock-output-names:
+    An ordered list of strings defining the names of the ASIU clocks
+
+Example:
+
+	osc: oscillator {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <25000000>;
+	};
+
+	asiu_clks: asiu_clks {
+		#clock-cells = <1>;
+		compatible = "brcm,cygnus-asiu-clk";
+		reg = <0x0301d048 0xc>, <0x180aa024 0x4>;
+		clocks = <&osc>;
+		clock-output-names = "keypad", "adc/touch", "pwm";
+	};
+
+Cygnus
+------
+PLL and leaf clock compatible strings for Cygnus are:
+    "brcm,cygnus-armpll"
+    "brcm,cygnus-genpll"
+    "brcm,cygnus-lcpll0"
+    "brcm,cygnus-mipipll"
+    "brcm,cygnus-asiu-clk"
+
+The following table defines the set of PLL/clock index and ID for Cygnus.
+These clock IDs are defined in:
+    "include/dt-bindings/clock/bcm-cygnus.h"
+
+    Clock      Source (Parent)  Index   ID
+    ---        -----            -----   ---------
+    crystal    N/A              N/A     N/A
+
+    armpll     crystal          N/A     N/A
+
+    keypad     crystal (ASIU)   0       BCM_CYGNUS_ASIU_KEYPAD_CLK
+    adc/tsc    crystal (ASIU)   1       BCM_CYGNUS_ASIU_ADC_CLK
+    pwm        crystal (ASIU)   2       BCM_CYGNUS_ASIU_PWM_CLK
+
+    genpll     crystal          0       BCM_CYGNUS_GENPLL
+    axi21      genpll           1       BCM_CYGNUS_GENPLL_AXI21_CLK
+    250mhz     genpll           2       BCM_CYGNUS_GENPLL_250MHZ_CLK
+    ihost_sys  genpll           3       BCM_CYGNUS_GENPLL_IHOST_SYS_CLK
+    enet_sw    genpll           4       BCM_CYGNUS_GENPLL_ENET_SW_CLK
+    audio_125  genpll           5       BCM_CYGNUS_GENPLL_AUDIO_125_CLK
+    can        genpll           6       BCM_CYGNUS_GENPLL_CAN_CLK
+
+    lcpll0     crystal          0       BCM_CYGNUS_LCPLL0
+    pcie_phy   lcpll0           1       BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK
+    ddr_phy    lcpll0           2       BCM_CYGNUS_LCPLL0_DDR_PHY_CLK
+    sdio       lcpll0           3       BCM_CYGNUS_LCPLL0_SDIO_CLK
+    usb_phy    lcpll0           4       BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK
+    smart_card lcpll0           5       BCM_CYGNUS_LCPLL0_SMART_CARD_CLK
+    ch5_unused lcpll0           6       BCM_CYGNUS_LCPLL0_CH5_UNUSED
+
+    mipipll    crystal          0       BCM_CYGNUS_MIPIPLL
+    ch0_unused mipipll          1       BCM_CYGNUS_MIPIPLL_CH0_UNUSED
+    ch1_lcd    mipipll          2       BCM_CYGNUS_MIPIPLL_CH1_LCD
+    ch2_v3d    mipipll          3       BCM_CYGNUS_MIPIPLL_CH2_V3D
+    ch3_unused mipipll          4       BCM_CYGNUS_MIPIPLL_CH3_UNUSED
+    ch4_unused mipipll          5       BCM_CYGNUS_MIPIPLL_CH4_UNUSED
+    ch5_unused mipipll          6       BCM_CYGNUS_MIPIPLL_CH5_UNUSED

From 5fe225c105fd54debae1699ec0f6aef1e73376d0 Mon Sep 17 00:00:00 2001
From: Ray Jui <rjui@broadcom.com>
Date: Tue, 5 May 2015 11:13:19 -0700
Subject: [PATCH 119/135] clk: iproc: add initial common clock support

This adds basic and generic support for various iProc PLLs and clocks
including the ARMPLL, GENPLL, LCPLL, MIPIPLL, and ASIU clocks.

SoCs under the iProc architecture can define their specific register
offsets and clock parameters for their PLL and clock controllers. These
parameters can be passed as arugments into the generic iProc PLL and
clock setup functions

Derived from code originally provided by Jonathan Richardson
<jonathar@broadcom.com>

Signed-off-by: Ray Jui <rjui@broadcom.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 drivers/clk/bcm/Kconfig            |   9 +
 drivers/clk/bcm/Makefile           |   1 +
 drivers/clk/bcm/clk-iproc-armpll.c | 282 ++++++++++++
 drivers/clk/bcm/clk-iproc-asiu.c   | 276 +++++++++++
 drivers/clk/bcm/clk-iproc-pll.c    | 716 +++++++++++++++++++++++++++++
 drivers/clk/bcm/clk-iproc.h        | 178 +++++++
 6 files changed, 1462 insertions(+)
 create mode 100644 drivers/clk/bcm/clk-iproc-armpll.c
 create mode 100644 drivers/clk/bcm/clk-iproc-asiu.c
 create mode 100644 drivers/clk/bcm/clk-iproc-pll.c
 create mode 100644 drivers/clk/bcm/clk-iproc.h

diff --git a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig
index 75506e53075b..88febf53b276 100644
--- a/drivers/clk/bcm/Kconfig
+++ b/drivers/clk/bcm/Kconfig
@@ -7,3 +7,12 @@ config CLK_BCM_KONA
 	  Enable common clock framework support for Broadcom SoCs
 	  using "Kona" style clock control units, including those
 	  in the BCM281xx and BCM21664 families.
+
+config COMMON_CLK_IPROC
+	bool "Broadcom iProc clock support"
+	depends on ARCH_BCM_IPROC
+	depends on COMMON_CLK
+	default ARCH_BCM_IPROC
+	help
+	  Enable common clock framework support for Broadcom SoCs
+	  based on the iProc architecture
diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile
index 6297d05a9a10..0facbbc5652c 100644
--- a/drivers/clk/bcm/Makefile
+++ b/drivers/clk/bcm/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_CLK_BCM_KONA)	+= clk-kona.o
 obj-$(CONFIG_CLK_BCM_KONA)	+= clk-kona-setup.o
 obj-$(CONFIG_CLK_BCM_KONA)	+= clk-bcm281xx.o
 obj-$(CONFIG_CLK_BCM_KONA)	+= clk-bcm21664.o
+obj-$(CONFIG_COMMON_CLK_IPROC)	+= clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o
diff --git a/drivers/clk/bcm/clk-iproc-armpll.c b/drivers/clk/bcm/clk-iproc-armpll.c
new file mode 100644
index 000000000000..a196ee28a17a
--- /dev/null
+++ b/drivers/clk/bcm/clk-iproc-armpll.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2014 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/clkdev.h>
+#include <linux/of_address.h>
+
+#define IPROC_CLK_MAX_FREQ_POLICY                    0x3
+#define IPROC_CLK_POLICY_FREQ_OFFSET                 0x008
+#define IPROC_CLK_POLICY_FREQ_POLICY_FREQ_SHIFT      8
+#define IPROC_CLK_POLICY_FREQ_POLICY_FREQ_MASK       0x7
+
+#define IPROC_CLK_PLLARMA_OFFSET                     0xc00
+#define IPROC_CLK_PLLARMA_LOCK_SHIFT                 28
+#define IPROC_CLK_PLLARMA_PDIV_SHIFT                 24
+#define IPROC_CLK_PLLARMA_PDIV_MASK                  0xf
+#define IPROC_CLK_PLLARMA_NDIV_INT_SHIFT             8
+#define IPROC_CLK_PLLARMA_NDIV_INT_MASK              0x3ff
+
+#define IPROC_CLK_PLLARMB_OFFSET                     0xc04
+#define IPROC_CLK_PLLARMB_NDIV_FRAC_MASK             0xfffff
+
+#define IPROC_CLK_PLLARMC_OFFSET                     0xc08
+#define IPROC_CLK_PLLARMC_BYPCLK_EN_SHIFT            8
+#define IPROC_CLK_PLLARMC_MDIV_MASK                  0xff
+
+#define IPROC_CLK_PLLARMCTL5_OFFSET                  0xc20
+#define IPROC_CLK_PLLARMCTL5_H_MDIV_MASK             0xff
+
+#define IPROC_CLK_PLLARM_OFFSET_OFFSET               0xc24
+#define IPROC_CLK_PLLARM_SW_CTL_SHIFT                29
+#define IPROC_CLK_PLLARM_NDIV_INT_OFFSET_SHIFT       20
+#define IPROC_CLK_PLLARM_NDIV_INT_OFFSET_MASK        0xff
+#define IPROC_CLK_PLLARM_NDIV_FRAC_OFFSET_MASK       0xfffff
+
+#define IPROC_CLK_ARM_DIV_OFFSET                     0xe00
+#define IPROC_CLK_ARM_DIV_PLL_SELECT_OVERRIDE_SHIFT  4
+#define IPROC_CLK_ARM_DIV_ARM_PLL_SELECT_MASK        0xf
+
+#define IPROC_CLK_POLICY_DBG_OFFSET                  0xec0
+#define IPROC_CLK_POLICY_DBG_ACT_FREQ_SHIFT          12
+#define IPROC_CLK_POLICY_DBG_ACT_FREQ_MASK           0x7
+
+enum iproc_arm_pll_fid {
+	ARM_PLL_FID_CRYSTAL_CLK   = 0,
+	ARM_PLL_FID_SYS_CLK       = 2,
+	ARM_PLL_FID_CH0_SLOW_CLK  = 6,
+	ARM_PLL_FID_CH1_FAST_CLK  = 7
+};
+
+struct iproc_arm_pll {
+	struct clk_hw hw;
+	void __iomem *base;
+	unsigned long rate;
+};
+
+#define to_iproc_arm_pll(hw) container_of(hw, struct iproc_arm_pll, hw)
+
+static unsigned int __get_fid(struct iproc_arm_pll *pll)
+{
+	u32 val;
+	unsigned int policy, fid, active_fid;
+
+	val = readl(pll->base + IPROC_CLK_ARM_DIV_OFFSET);
+	if (val & (1 << IPROC_CLK_ARM_DIV_PLL_SELECT_OVERRIDE_SHIFT))
+		policy = val & IPROC_CLK_ARM_DIV_ARM_PLL_SELECT_MASK;
+	else
+		policy = 0;
+
+	/* something is seriously wrong */
+	BUG_ON(policy > IPROC_CLK_MAX_FREQ_POLICY);
+
+	val = readl(pll->base + IPROC_CLK_POLICY_FREQ_OFFSET);
+	fid = (val >> (IPROC_CLK_POLICY_FREQ_POLICY_FREQ_SHIFT * policy)) &
+		IPROC_CLK_POLICY_FREQ_POLICY_FREQ_MASK;
+
+	val = readl(pll->base + IPROC_CLK_POLICY_DBG_OFFSET);
+	active_fid = IPROC_CLK_POLICY_DBG_ACT_FREQ_MASK &
+		(val >> IPROC_CLK_POLICY_DBG_ACT_FREQ_SHIFT);
+	if (fid != active_fid) {
+		pr_debug("%s: fid override %u->%u\n", __func__,	fid,
+				active_fid);
+		fid = active_fid;
+	}
+
+	pr_debug("%s: active fid: %u\n", __func__, fid);
+
+	return fid;
+}
+
+/*
+ * Determine the mdiv (post divider) based on the frequency ID being used.
+ * There are 4 sources that can be used to derive the output clock rate:
+ *    - 25 MHz Crystal
+ *    - System clock
+ *    - PLL channel 0 (slow clock)
+ *    - PLL channel 1 (fast clock)
+ */
+static int __get_mdiv(struct iproc_arm_pll *pll)
+{
+	unsigned int fid;
+	int mdiv;
+	u32 val;
+
+	fid = __get_fid(pll);
+
+	switch (fid) {
+	case ARM_PLL_FID_CRYSTAL_CLK:
+	case ARM_PLL_FID_SYS_CLK:
+		mdiv = 1;
+		break;
+
+	case ARM_PLL_FID_CH0_SLOW_CLK:
+		val = readl(pll->base + IPROC_CLK_PLLARMC_OFFSET);
+		mdiv = val & IPROC_CLK_PLLARMC_MDIV_MASK;
+		if (mdiv == 0)
+			mdiv = 256;
+		break;
+
+	case ARM_PLL_FID_CH1_FAST_CLK:
+		val = readl(pll->base +	IPROC_CLK_PLLARMCTL5_OFFSET);
+		mdiv = val & IPROC_CLK_PLLARMCTL5_H_MDIV_MASK;
+		if (mdiv == 0)
+			mdiv = 256;
+		break;
+
+	default:
+		mdiv = -EFAULT;
+	}
+
+	return mdiv;
+}
+
+static unsigned int __get_ndiv(struct iproc_arm_pll *pll)
+{
+	u32 val;
+	unsigned int ndiv_int, ndiv_frac, ndiv;
+
+	val = readl(pll->base + IPROC_CLK_PLLARM_OFFSET_OFFSET);
+	if (val & (1 << IPROC_CLK_PLLARM_SW_CTL_SHIFT)) {
+		/*
+		 * offset mode is active. Read the ndiv from the PLLARM OFFSET
+		 * register
+		 */
+		ndiv_int = (val >> IPROC_CLK_PLLARM_NDIV_INT_OFFSET_SHIFT) &
+			IPROC_CLK_PLLARM_NDIV_INT_OFFSET_MASK;
+		if (ndiv_int == 0)
+			ndiv_int = 256;
+
+		ndiv_frac = val & IPROC_CLK_PLLARM_NDIV_FRAC_OFFSET_MASK;
+	} else {
+		/* offset mode not active */
+		val = readl(pll->base + IPROC_CLK_PLLARMA_OFFSET);
+		ndiv_int = (val >> IPROC_CLK_PLLARMA_NDIV_INT_SHIFT) &
+			IPROC_CLK_PLLARMA_NDIV_INT_MASK;
+		if (ndiv_int == 0)
+			ndiv_int = 1024;
+
+		val = readl(pll->base + IPROC_CLK_PLLARMB_OFFSET);
+		ndiv_frac = val & IPROC_CLK_PLLARMB_NDIV_FRAC_MASK;
+	}
+
+	ndiv = (ndiv_int << 20) | ndiv_frac;
+
+	return ndiv;
+}
+
+/*
+ * The output frequency of the ARM PLL is calculated based on the ARM PLL
+ * divider values:
+ *   pdiv = ARM PLL pre-divider
+ *   ndiv = ARM PLL multiplier
+ *   mdiv = ARM PLL post divider
+ *
+ * The frequency is calculated by:
+ *   ((ndiv * parent clock rate) / pdiv) / mdiv
+ */
+static unsigned long iproc_arm_pll_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct iproc_arm_pll *pll = to_iproc_arm_pll(hw);
+	u32 val;
+	int mdiv;
+	u64 ndiv;
+	unsigned int pdiv;
+
+	/* in bypass mode, use parent rate */
+	val = readl(pll->base + IPROC_CLK_PLLARMC_OFFSET);
+	if (val & (1 << IPROC_CLK_PLLARMC_BYPCLK_EN_SHIFT)) {
+		pll->rate = parent_rate;
+		return pll->rate;
+	}
+
+	/* PLL needs to be locked */
+	val = readl(pll->base + IPROC_CLK_PLLARMA_OFFSET);
+	if (!(val & (1 << IPROC_CLK_PLLARMA_LOCK_SHIFT))) {
+		pll->rate = 0;
+		return 0;
+	}
+
+	pdiv = (val >> IPROC_CLK_PLLARMA_PDIV_SHIFT) &
+		IPROC_CLK_PLLARMA_PDIV_MASK;
+	if (pdiv == 0)
+		pdiv = 16;
+
+	ndiv = __get_ndiv(pll);
+	mdiv = __get_mdiv(pll);
+	if (mdiv <= 0) {
+		pll->rate = 0;
+		return 0;
+	}
+	pll->rate = (ndiv * parent_rate) >> 20;
+	pll->rate = (pll->rate / pdiv) / mdiv;
+
+	pr_debug("%s: ARM PLL rate: %lu. parent rate: %lu\n", __func__,
+		 pll->rate, parent_rate);
+	pr_debug("%s: ndiv_int: %u, pdiv: %u, mdiv: %d\n", __func__,
+		 (unsigned int)(ndiv >> 20), pdiv, mdiv);
+
+	return pll->rate;
+}
+
+static const struct clk_ops iproc_arm_pll_ops = {
+	.recalc_rate = iproc_arm_pll_recalc_rate,
+};
+
+void __init iproc_armpll_setup(struct device_node *node)
+{
+	int ret;
+	struct clk *clk;
+	struct iproc_arm_pll *pll;
+	struct clk_init_data init;
+	const char *parent_name;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (WARN_ON(!pll))
+		return;
+
+	pll->base = of_iomap(node, 0);
+	if (WARN_ON(!pll->base))
+		goto err_free_pll;
+
+	init.name = node->name;
+	init.ops = &iproc_arm_pll_ops;
+	init.flags = 0;
+	parent_name = of_clk_get_parent_name(node, 0);
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+	pll->hw.init = &init;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (WARN_ON(IS_ERR(clk)))
+		goto err_iounmap;
+
+	ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	if (WARN_ON(ret))
+		goto err_clk_unregister;
+
+	return;
+
+err_clk_unregister:
+	clk_unregister(clk);
+err_iounmap:
+	iounmap(pll->base);
+err_free_pll:
+	kfree(pll);
+}
diff --git a/drivers/clk/bcm/clk-iproc-asiu.c b/drivers/clk/bcm/clk-iproc-asiu.c
new file mode 100644
index 000000000000..e19c09cd9645
--- /dev/null
+++ b/drivers/clk/bcm/clk-iproc-asiu.c
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2014 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/clkdev.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+
+#include "clk-iproc.h"
+
+struct iproc_asiu;
+
+struct iproc_asiu_clk {
+	struct clk_hw hw;
+	const char *name;
+	struct iproc_asiu *asiu;
+	unsigned long rate;
+	struct iproc_asiu_div div;
+	struct iproc_asiu_gate gate;
+};
+
+struct iproc_asiu {
+	void __iomem *div_base;
+	void __iomem *gate_base;
+
+	struct clk_onecell_data clk_data;
+	struct iproc_asiu_clk *clks;
+};
+
+#define to_asiu_clk(hw) container_of(hw, struct iproc_asiu_clk, hw)
+
+static int iproc_asiu_clk_enable(struct clk_hw *hw)
+{
+	struct iproc_asiu_clk *clk = to_asiu_clk(hw);
+	struct iproc_asiu *asiu = clk->asiu;
+	u32 val;
+
+	/* some clocks at the ASIU level are always enabled */
+	if (clk->gate.offset == IPROC_CLK_INVALID_OFFSET)
+		return 0;
+
+	val = readl(asiu->gate_base + clk->gate.offset);
+	val |= (1 << clk->gate.en_shift);
+	writel(val, asiu->gate_base + clk->gate.offset);
+
+	return 0;
+}
+
+static void iproc_asiu_clk_disable(struct clk_hw *hw)
+{
+	struct iproc_asiu_clk *clk = to_asiu_clk(hw);
+	struct iproc_asiu *asiu = clk->asiu;
+	u32 val;
+
+	/* some clocks at the ASIU level are always enabled */
+	if (clk->gate.offset == IPROC_CLK_INVALID_OFFSET)
+		return;
+
+	val = readl(asiu->gate_base + clk->gate.offset);
+	val &= ~(1 << clk->gate.en_shift);
+	writel(val, asiu->gate_base + clk->gate.offset);
+}
+
+static unsigned long iproc_asiu_clk_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
+{
+	struct iproc_asiu_clk *clk = to_asiu_clk(hw);
+	struct iproc_asiu *asiu = clk->asiu;
+	u32 val;
+	unsigned int div_h, div_l;
+
+	if (parent_rate == 0) {
+		clk->rate = 0;
+		return 0;
+	}
+
+	/* if clock divisor is not enabled, simply return parent rate */
+	val = readl(asiu->div_base + clk->div.offset);
+	if ((val & (1 << clk->div.en_shift)) == 0) {
+		clk->rate = parent_rate;
+		return parent_rate;
+	}
+
+	/* clock rate = parent rate / (high_div + 1) + (low_div + 1) */
+	div_h = (val >> clk->div.high_shift) & bit_mask(clk->div.high_width);
+	div_h++;
+	div_l = (val >> clk->div.low_shift) & bit_mask(clk->div.low_width);
+	div_l++;
+
+	clk->rate = parent_rate / (div_h + div_l);
+	pr_debug("%s: rate: %lu. parent rate: %lu div_h: %u div_l: %u\n",
+		 __func__, clk->rate, parent_rate, div_h, div_l);
+
+	return clk->rate;
+}
+
+static long iproc_asiu_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				      unsigned long *parent_rate)
+{
+	unsigned int div;
+
+	if (rate == 0 || *parent_rate == 0)
+		return -EINVAL;
+
+	if (rate == *parent_rate)
+		return *parent_rate;
+
+	div = DIV_ROUND_UP(*parent_rate, rate);
+	if (div < 2)
+		return *parent_rate;
+
+	return *parent_rate / div;
+}
+
+static int iproc_asiu_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long parent_rate)
+{
+	struct iproc_asiu_clk *clk = to_asiu_clk(hw);
+	struct iproc_asiu *asiu = clk->asiu;
+	unsigned int div, div_h, div_l;
+	u32 val;
+
+	if (rate == 0 || parent_rate == 0)
+		return -EINVAL;
+
+	/* simply disable the divisor if one wants the same rate as parent */
+	if (rate == parent_rate) {
+		val = readl(asiu->div_base + clk->div.offset);
+		val &= ~(1 << clk->div.en_shift);
+		writel(val, asiu->div_base + clk->div.offset);
+		return 0;
+	}
+
+	div = DIV_ROUND_UP(parent_rate, rate);
+	if (div < 2)
+		return -EINVAL;
+
+	div_h = div_l = div >> 1;
+	div_h--;
+	div_l--;
+
+	val = readl(asiu->div_base + clk->div.offset);
+	val |= 1 << clk->div.en_shift;
+	if (div_h) {
+		val &= ~(bit_mask(clk->div.high_width)
+			 << clk->div.high_shift);
+		val |= div_h << clk->div.high_shift;
+	} else {
+		val &= ~(bit_mask(clk->div.high_width)
+			 << clk->div.high_shift);
+	}
+	if (div_l) {
+		val &= ~(bit_mask(clk->div.low_width) << clk->div.low_shift);
+		val |= div_l << clk->div.low_shift;
+	} else {
+		val &= ~(bit_mask(clk->div.low_width) << clk->div.low_shift);
+	}
+	writel(val, asiu->div_base + clk->div.offset);
+
+	return 0;
+}
+
+static const struct clk_ops iproc_asiu_ops = {
+	.enable = iproc_asiu_clk_enable,
+	.disable = iproc_asiu_clk_disable,
+	.recalc_rate = iproc_asiu_clk_recalc_rate,
+	.round_rate = iproc_asiu_clk_round_rate,
+	.set_rate = iproc_asiu_clk_set_rate,
+};
+
+void __init iproc_asiu_setup(struct device_node *node,
+			     const struct iproc_asiu_div *div,
+			     const struct iproc_asiu_gate *gate,
+			     unsigned int num_clks)
+{
+	int i, ret;
+	struct iproc_asiu *asiu;
+
+	if (WARN_ON(!gate || !div))
+		return;
+
+	asiu = kzalloc(sizeof(*asiu), GFP_KERNEL);
+	if (WARN_ON(!asiu))
+		return;
+
+	asiu->clk_data.clk_num = num_clks;
+	asiu->clk_data.clks = kcalloc(num_clks, sizeof(*asiu->clk_data.clks),
+				      GFP_KERNEL);
+	if (WARN_ON(!asiu->clk_data.clks))
+		goto err_clks;
+
+	asiu->clks = kcalloc(num_clks, sizeof(*asiu->clks), GFP_KERNEL);
+	if (WARN_ON(!asiu->clks))
+		goto err_asiu_clks;
+
+	asiu->div_base = of_iomap(node, 0);
+	if (WARN_ON(!asiu->div_base))
+		goto err_iomap_div;
+
+	asiu->gate_base = of_iomap(node, 1);
+	if (WARN_ON(!asiu->gate_base))
+		goto err_iomap_gate;
+
+	for (i = 0; i < num_clks; i++) {
+		struct clk_init_data init;
+		struct clk *clk;
+		const char *parent_name;
+		struct iproc_asiu_clk *asiu_clk;
+		const char *clk_name;
+
+		clk_name = kzalloc(IPROC_CLK_NAME_LEN, GFP_KERNEL);
+		if (WARN_ON(!clk_name))
+			goto err_clk_register;
+
+		ret = of_property_read_string_index(node, "clock-output-names",
+						    i, &clk_name);
+		if (WARN_ON(ret))
+			goto err_clk_register;
+
+		asiu_clk = &asiu->clks[i];
+		asiu_clk->name = clk_name;
+		asiu_clk->asiu = asiu;
+		asiu_clk->div = div[i];
+		asiu_clk->gate = gate[i];
+		init.name = clk_name;
+		init.ops = &iproc_asiu_ops;
+		init.flags = 0;
+		parent_name = of_clk_get_parent_name(node, 0);
+		init.parent_names = (parent_name ? &parent_name : NULL);
+		init.num_parents = (parent_name ? 1 : 0);
+		asiu_clk->hw.init = &init;
+
+		clk = clk_register(NULL, &asiu_clk->hw);
+		if (WARN_ON(IS_ERR(clk)))
+			goto err_clk_register;
+		asiu->clk_data.clks[i] = clk;
+	}
+
+	ret = of_clk_add_provider(node, of_clk_src_onecell_get,
+				  &asiu->clk_data);
+	if (WARN_ON(ret))
+		goto err_clk_register;
+
+	return;
+
+err_clk_register:
+	for (i = 0; i < num_clks; i++)
+		kfree(asiu->clks[i].name);
+	iounmap(asiu->gate_base);
+
+err_iomap_gate:
+	iounmap(asiu->div_base);
+
+err_iomap_div:
+	kfree(asiu->clks);
+
+err_asiu_clks:
+	kfree(asiu->clk_data.clks);
+
+err_clks:
+	kfree(asiu);
+}
diff --git a/drivers/clk/bcm/clk-iproc-pll.c b/drivers/clk/bcm/clk-iproc-pll.c
new file mode 100644
index 000000000000..46fb84bc2674
--- /dev/null
+++ b/drivers/clk/bcm/clk-iproc-pll.c
@@ -0,0 +1,716 @@
+/*
+ * Copyright (C) 2014 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/clkdev.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+
+#include "clk-iproc.h"
+
+#define PLL_VCO_HIGH_SHIFT 19
+#define PLL_VCO_LOW_SHIFT  30
+
+/* number of delay loops waiting for PLL to lock */
+#define LOCK_DELAY 100
+
+/* number of VCO frequency bands */
+#define NUM_FREQ_BANDS 8
+
+#define NUM_KP_BANDS 3
+enum kp_band {
+	KP_BAND_MID = 0,
+	KP_BAND_HIGH,
+	KP_BAND_HIGH_HIGH
+};
+
+static const unsigned int kp_table[NUM_KP_BANDS][NUM_FREQ_BANDS] = {
+	{ 5, 6, 6, 7, 7, 8, 9, 10 },
+	{ 4, 4, 5, 5, 6, 7, 8, 9  },
+	{ 4, 5, 5, 6, 7, 8, 9, 10 },
+};
+
+static const unsigned long ref_freq_table[NUM_FREQ_BANDS][2] = {
+	{ 10000000,  12500000  },
+	{ 12500000,  15000000  },
+	{ 15000000,  20000000  },
+	{ 20000000,  25000000  },
+	{ 25000000,  50000000  },
+	{ 50000000,  75000000  },
+	{ 75000000,  100000000 },
+	{ 100000000, 125000000 },
+};
+
+enum vco_freq_range {
+	VCO_LOW       = 700000000U,
+	VCO_MID       = 1200000000U,
+	VCO_HIGH      = 2200000000U,
+	VCO_HIGH_HIGH = 3100000000U,
+	VCO_MAX       = 4000000000U,
+};
+
+struct iproc_pll;
+
+struct iproc_clk {
+	struct clk_hw hw;
+	const char *name;
+	struct iproc_pll *pll;
+	unsigned long rate;
+	const struct iproc_clk_ctrl *ctrl;
+};
+
+struct iproc_pll {
+	void __iomem *pll_base;
+	void __iomem *pwr_base;
+	void __iomem *asiu_base;
+
+	const struct iproc_pll_ctrl *ctrl;
+	const struct iproc_pll_vco_param *vco_param;
+	unsigned int num_vco_entries;
+
+	struct clk_onecell_data clk_data;
+	struct iproc_clk *clks;
+};
+
+#define to_iproc_clk(hw) container_of(hw, struct iproc_clk, hw)
+
+/*
+ * Based on the target frequency, find a match from the VCO frequency parameter
+ * table and return its index
+ */
+static int pll_get_rate_index(struct iproc_pll *pll, unsigned int target_rate)
+{
+	int i;
+
+	for (i = 0; i < pll->num_vco_entries; i++)
+		if (target_rate == pll->vco_param[i].rate)
+			break;
+
+	if (i >= pll->num_vco_entries)
+		return -EINVAL;
+
+	return i;
+}
+
+static int get_kp(unsigned long ref_freq, enum kp_band kp_index)
+{
+	int i;
+
+	if (ref_freq < ref_freq_table[0][0])
+		return -EINVAL;
+
+	for (i = 0; i < NUM_FREQ_BANDS; i++) {
+		if (ref_freq >= ref_freq_table[i][0] &&
+		    ref_freq < ref_freq_table[i][1])
+			return kp_table[kp_index][i];
+	}
+	return -EINVAL;
+}
+
+static int pll_wait_for_lock(struct iproc_pll *pll)
+{
+	int i;
+	const struct iproc_pll_ctrl *ctrl = pll->ctrl;
+
+	for (i = 0; i < LOCK_DELAY; i++) {
+		u32 val = readl(pll->pll_base + ctrl->status.offset);
+
+		if (val & (1 << ctrl->status.shift))
+			return 0;
+		udelay(10);
+	}
+
+	return -EIO;
+}
+
+static void __pll_disable(struct iproc_pll *pll)
+{
+	const struct iproc_pll_ctrl *ctrl = pll->ctrl;
+	u32 val;
+
+	if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
+		val = readl(pll->asiu_base + ctrl->asiu.offset);
+		val &= ~(1 << ctrl->asiu.en_shift);
+		writel(val, pll->asiu_base + ctrl->asiu.offset);
+	}
+
+	/* latch input value so core power can be shut down */
+	val = readl(pll->pwr_base + ctrl->aon.offset);
+	val |= (1 << ctrl->aon.iso_shift);
+	writel(val, pll->pwr_base + ctrl->aon.offset);
+
+	/* power down the core */
+	val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
+	writel(val, pll->pwr_base + ctrl->aon.offset);
+}
+
+static int __pll_enable(struct iproc_pll *pll)
+{
+	const struct iproc_pll_ctrl *ctrl = pll->ctrl;
+	u32 val;
+
+	/* power up the PLL and make sure it's not latched */
+	val = readl(pll->pwr_base + ctrl->aon.offset);
+	val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
+	val &= ~(1 << ctrl->aon.iso_shift);
+	writel(val, pll->pwr_base + ctrl->aon.offset);
+
+	/* certain PLLs also need to be ungated from the ASIU top level */
+	if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
+		val = readl(pll->asiu_base + ctrl->asiu.offset);
+		val |= (1 << ctrl->asiu.en_shift);
+		writel(val, pll->asiu_base + ctrl->asiu.offset);
+	}
+
+	return 0;
+}
+
+static void __pll_put_in_reset(struct iproc_pll *pll)
+{
+	u32 val;
+	const struct iproc_pll_ctrl *ctrl = pll->ctrl;
+	const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
+
+	val = readl(pll->pll_base + reset->offset);
+	val &= ~(1 << reset->reset_shift | 1 << reset->p_reset_shift);
+	writel(val, pll->pll_base + reset->offset);
+	if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
+		readl(pll->pll_base + reset->offset);
+}
+
+static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp,
+				  unsigned int ka, unsigned int ki)
+{
+	u32 val;
+	const struct iproc_pll_ctrl *ctrl = pll->ctrl;
+	const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
+
+	val = readl(pll->pll_base + reset->offset);
+	val &= ~(bit_mask(reset->ki_width) << reset->ki_shift |
+		 bit_mask(reset->kp_width) << reset->kp_shift |
+		 bit_mask(reset->ka_width) << reset->ka_shift);
+	val |=  ki << reset->ki_shift | kp << reset->kp_shift |
+		ka << reset->ka_shift;
+	val |= 1 << reset->reset_shift | 1 << reset->p_reset_shift;
+	writel(val, pll->pll_base + reset->offset);
+	if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
+		readl(pll->pll_base + reset->offset);
+}
+
+static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
+			unsigned long parent_rate)
+{
+	struct iproc_pll *pll = clk->pll;
+	const struct iproc_pll_vco_param *vco = &pll->vco_param[rate_index];
+	const struct iproc_pll_ctrl *ctrl = pll->ctrl;
+	int ka = 0, ki, kp, ret;
+	unsigned long rate = vco->rate;
+	u32 val;
+	enum kp_band kp_index;
+	unsigned long ref_freq;
+
+	/*
+	 * reference frequency = parent frequency / PDIV
+	 * If PDIV = 0, then it becomes a multiplier (x2)
+	 */
+	if (vco->pdiv == 0)
+		ref_freq = parent_rate * 2;
+	else
+		ref_freq = parent_rate / vco->pdiv;
+
+	/* determine Ki and Kp index based on target VCO frequency */
+	if (rate >= VCO_LOW && rate < VCO_HIGH) {
+		ki = 4;
+		kp_index = KP_BAND_MID;
+	} else if (rate >= VCO_HIGH && rate && rate < VCO_HIGH_HIGH) {
+		ki = 3;
+		kp_index = KP_BAND_HIGH;
+	} else if (rate >= VCO_HIGH_HIGH && rate < VCO_MAX) {
+		ki = 3;
+		kp_index = KP_BAND_HIGH_HIGH;
+	} else {
+		pr_err("%s: pll: %s has invalid rate: %lu\n", __func__,
+				clk->name, rate);
+		return -EINVAL;
+	}
+
+	kp = get_kp(ref_freq, kp_index);
+	if (kp < 0) {
+		pr_err("%s: pll: %s has invalid kp\n", __func__, clk->name);
+		return kp;
+	}
+
+	ret = __pll_enable(pll);
+	if (ret) {
+		pr_err("%s: pll: %s fails to enable\n", __func__, clk->name);
+		return ret;
+	}
+
+	/* put PLL in reset */
+	__pll_put_in_reset(pll);
+
+	writel(0, pll->pll_base + ctrl->vco_ctrl.u_offset);
+	if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
+		readl(pll->pll_base + ctrl->vco_ctrl.u_offset);
+	val = readl(pll->pll_base + ctrl->vco_ctrl.l_offset);
+
+	if (rate >= VCO_LOW && rate < VCO_MID)
+		val |= (1 << PLL_VCO_LOW_SHIFT);
+
+	if (rate < VCO_HIGH)
+		val &= ~(1 << PLL_VCO_HIGH_SHIFT);
+	else
+		val |= (1 << PLL_VCO_HIGH_SHIFT);
+
+	writel(val, pll->pll_base + ctrl->vco_ctrl.l_offset);
+	if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
+		readl(pll->pll_base + ctrl->vco_ctrl.l_offset);
+
+	/* program integer part of NDIV */
+	val = readl(pll->pll_base + ctrl->ndiv_int.offset);
+	val &= ~(bit_mask(ctrl->ndiv_int.width) << ctrl->ndiv_int.shift);
+	val |= vco->ndiv_int << ctrl->ndiv_int.shift;
+	writel(val, pll->pll_base + ctrl->ndiv_int.offset);
+	if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
+		readl(pll->pll_base + ctrl->ndiv_int.offset);
+
+	/* program fractional part of NDIV */
+	if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
+		val = readl(pll->pll_base + ctrl->ndiv_frac.offset);
+		val &= ~(bit_mask(ctrl->ndiv_frac.width) <<
+			 ctrl->ndiv_frac.shift);
+		val |= vco->ndiv_frac << ctrl->ndiv_frac.shift;
+		writel(val, pll->pll_base + ctrl->ndiv_frac.offset);
+		if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
+			readl(pll->pll_base + ctrl->ndiv_frac.offset);
+	}
+
+	/* program PDIV */
+	val = readl(pll->pll_base + ctrl->pdiv.offset);
+	val &= ~(bit_mask(ctrl->pdiv.width) << ctrl->pdiv.shift);
+	val |= vco->pdiv << ctrl->pdiv.shift;
+	writel(val, pll->pll_base + ctrl->pdiv.offset);
+	if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
+		readl(pll->pll_base + ctrl->pdiv.offset);
+
+	__pll_bring_out_reset(pll, kp, ka, ki);
+
+	ret = pll_wait_for_lock(pll);
+	if (ret < 0) {
+		pr_err("%s: pll: %s failed to lock\n", __func__, clk->name);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int iproc_pll_enable(struct clk_hw *hw)
+{
+	struct iproc_clk *clk = to_iproc_clk(hw);
+	struct iproc_pll *pll = clk->pll;
+
+	return __pll_enable(pll);
+}
+
+static void iproc_pll_disable(struct clk_hw *hw)
+{
+	struct iproc_clk *clk = to_iproc_clk(hw);
+	struct iproc_pll *pll = clk->pll;
+	const struct iproc_pll_ctrl *ctrl = pll->ctrl;
+
+	if (ctrl->flags & IPROC_CLK_AON)
+		return;
+
+	__pll_disable(pll);
+}
+
+static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw,
+					   unsigned long parent_rate)
+{
+	struct iproc_clk *clk = to_iproc_clk(hw);
+	struct iproc_pll *pll = clk->pll;
+	const struct iproc_pll_ctrl *ctrl = pll->ctrl;
+	u32 val;
+	u64 ndiv;
+	unsigned int ndiv_int, ndiv_frac, pdiv;
+
+	if (parent_rate == 0)
+		return 0;
+
+	/* PLL needs to be locked */
+	val = readl(pll->pll_base + ctrl->status.offset);
+	if ((val & (1 << ctrl->status.shift)) == 0) {
+		clk->rate = 0;
+		return 0;
+	}
+
+	/*
+	 * PLL output frequency =
+	 *
+	 * ((ndiv_int + ndiv_frac / 2^20) * (parent clock rate / pdiv)
+	 */
+	val = readl(pll->pll_base + ctrl->ndiv_int.offset);
+	ndiv_int = (val >> ctrl->ndiv_int.shift) &
+		bit_mask(ctrl->ndiv_int.width);
+	ndiv = ndiv_int << ctrl->ndiv_int.shift;
+
+	if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
+		val = readl(pll->pll_base + ctrl->ndiv_frac.offset);
+		ndiv_frac = (val >> ctrl->ndiv_frac.shift) &
+			bit_mask(ctrl->ndiv_frac.width);
+
+		if (ndiv_frac != 0)
+			ndiv = (ndiv_int << ctrl->ndiv_int.shift) | ndiv_frac;
+	}
+
+	val = readl(pll->pll_base + ctrl->pdiv.offset);
+	pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width);
+
+	clk->rate = (ndiv * parent_rate) >> ctrl->ndiv_int.shift;
+
+	if (pdiv == 0)
+		clk->rate *= 2;
+	else
+		clk->rate /= pdiv;
+
+	return clk->rate;
+}
+
+static long iproc_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long *parent_rate)
+{
+	unsigned i;
+	struct iproc_clk *clk = to_iproc_clk(hw);
+	struct iproc_pll *pll = clk->pll;
+
+	if (rate == 0 || *parent_rate == 0 || !pll->vco_param)
+		return -EINVAL;
+
+	for (i = 0; i < pll->num_vco_entries; i++) {
+		if (rate <= pll->vco_param[i].rate)
+			break;
+	}
+
+	if (i == pll->num_vco_entries)
+		i--;
+
+	return pll->vco_param[i].rate;
+}
+
+static int iproc_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct iproc_clk *clk = to_iproc_clk(hw);
+	struct iproc_pll *pll = clk->pll;
+	int rate_index, ret;
+
+	rate_index = pll_get_rate_index(pll, rate);
+	if (rate_index < 0)
+		return rate_index;
+
+	ret = pll_set_rate(clk, rate_index, parent_rate);
+	return ret;
+}
+
+static const struct clk_ops iproc_pll_ops = {
+	.enable = iproc_pll_enable,
+	.disable = iproc_pll_disable,
+	.recalc_rate = iproc_pll_recalc_rate,
+	.round_rate = iproc_pll_round_rate,
+	.set_rate = iproc_pll_set_rate,
+};
+
+static int iproc_clk_enable(struct clk_hw *hw)
+{
+	struct iproc_clk *clk = to_iproc_clk(hw);
+	const struct iproc_clk_ctrl *ctrl = clk->ctrl;
+	struct iproc_pll *pll = clk->pll;
+	u32 val;
+
+	/* channel enable is active low */
+	val = readl(pll->pll_base + ctrl->enable.offset);
+	val &= ~(1 << ctrl->enable.enable_shift);
+	writel(val, pll->pll_base + ctrl->enable.offset);
+
+	/* also make sure channel is not held */
+	val = readl(pll->pll_base + ctrl->enable.offset);
+	val &= ~(1 << ctrl->enable.hold_shift);
+	writel(val, pll->pll_base + ctrl->enable.offset);
+	if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
+		readl(pll->pll_base + ctrl->enable.offset);
+
+	return 0;
+}
+
+static void iproc_clk_disable(struct clk_hw *hw)
+{
+	struct iproc_clk *clk = to_iproc_clk(hw);
+	const struct iproc_clk_ctrl *ctrl = clk->ctrl;
+	struct iproc_pll *pll = clk->pll;
+	u32 val;
+
+	if (ctrl->flags & IPROC_CLK_AON)
+		return;
+
+	val = readl(pll->pll_base + ctrl->enable.offset);
+	val |= 1 << ctrl->enable.enable_shift;
+	writel(val, pll->pll_base + ctrl->enable.offset);
+	if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
+		readl(pll->pll_base + ctrl->enable.offset);
+}
+
+static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct iproc_clk *clk = to_iproc_clk(hw);
+	const struct iproc_clk_ctrl *ctrl = clk->ctrl;
+	struct iproc_pll *pll = clk->pll;
+	u32 val;
+	unsigned int mdiv;
+
+	if (parent_rate == 0)
+		return 0;
+
+	val = readl(pll->pll_base + ctrl->mdiv.offset);
+	mdiv = (val >> ctrl->mdiv.shift) & bit_mask(ctrl->mdiv.width);
+	if (mdiv == 0)
+		mdiv = 256;
+
+	clk->rate = parent_rate / mdiv;
+
+	return clk->rate;
+}
+
+static long iproc_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *parent_rate)
+{
+	unsigned int div;
+
+	if (rate == 0 || *parent_rate == 0)
+		return -EINVAL;
+
+	if (rate == *parent_rate)
+		return *parent_rate;
+
+	div = DIV_ROUND_UP(*parent_rate, rate);
+	if (div < 2)
+		return *parent_rate;
+
+	if (div > 256)
+		div = 256;
+
+	return *parent_rate / div;
+}
+
+static int iproc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct iproc_clk *clk = to_iproc_clk(hw);
+	const struct iproc_clk_ctrl *ctrl = clk->ctrl;
+	struct iproc_pll *pll = clk->pll;
+	u32 val;
+	unsigned int div;
+
+	if (rate == 0 || parent_rate == 0)
+		return -EINVAL;
+
+	div = DIV_ROUND_UP(parent_rate, rate);
+	if (div > 256)
+		return -EINVAL;
+
+	val = readl(pll->pll_base + ctrl->mdiv.offset);
+	if (div == 256) {
+		val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
+	} else {
+		val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
+		val |= div << ctrl->mdiv.shift;
+	}
+	writel(val, pll->pll_base + ctrl->mdiv.offset);
+	if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
+		readl(pll->pll_base + ctrl->mdiv.offset);
+	clk->rate = parent_rate / div;
+
+	return 0;
+}
+
+static const struct clk_ops iproc_clk_ops = {
+	.enable = iproc_clk_enable,
+	.disable = iproc_clk_disable,
+	.recalc_rate = iproc_clk_recalc_rate,
+	.round_rate = iproc_clk_round_rate,
+	.set_rate = iproc_clk_set_rate,
+};
+
+/**
+ * Some PLLs require the PLL SW override bit to be set before changes can be
+ * applied to the PLL
+ */
+static void iproc_pll_sw_cfg(struct iproc_pll *pll)
+{
+	const struct iproc_pll_ctrl *ctrl = pll->ctrl;
+
+	if (ctrl->flags & IPROC_CLK_PLL_NEEDS_SW_CFG) {
+		u32 val;
+
+		val = readl(pll->pll_base + ctrl->sw_ctrl.offset);
+		val |= BIT(ctrl->sw_ctrl.shift);
+		writel(val, pll->pll_base + ctrl->sw_ctrl.offset);
+		if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
+			readl(pll->pll_base + ctrl->sw_ctrl.offset);
+	}
+}
+
+void __init iproc_pll_clk_setup(struct device_node *node,
+				const struct iproc_pll_ctrl *pll_ctrl,
+				const struct iproc_pll_vco_param *vco,
+				unsigned int num_vco_entries,
+				const struct iproc_clk_ctrl *clk_ctrl,
+				unsigned int num_clks)
+{
+	int i, ret;
+	struct clk *clk;
+	struct iproc_pll *pll;
+	struct iproc_clk *iclk;
+	struct clk_init_data init;
+	const char *parent_name;
+
+	if (WARN_ON(!pll_ctrl) || WARN_ON(!clk_ctrl))
+		return;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (WARN_ON(!pll))
+		return;
+
+	pll->clk_data.clk_num = num_clks;
+	pll->clk_data.clks = kcalloc(num_clks, sizeof(*pll->clk_data.clks),
+				     GFP_KERNEL);
+	if (WARN_ON(!pll->clk_data.clks))
+		goto err_clk_data;
+
+	pll->clks = kcalloc(num_clks, sizeof(*pll->clks), GFP_KERNEL);
+	if (WARN_ON(!pll->clks))
+		goto err_clks;
+
+	pll->pll_base = of_iomap(node, 0);
+	if (WARN_ON(!pll->pll_base))
+		goto err_pll_iomap;
+
+	pll->pwr_base = of_iomap(node, 1);
+	if (WARN_ON(!pll->pwr_base))
+		goto err_pwr_iomap;
+
+	/* some PLLs require gating control at the top ASIU level */
+	if (pll_ctrl->flags & IPROC_CLK_PLL_ASIU) {
+		pll->asiu_base = of_iomap(node, 2);
+		if (WARN_ON(!pll->asiu_base))
+			goto err_asiu_iomap;
+	}
+
+	/* initialize and register the PLL itself */
+	pll->ctrl = pll_ctrl;
+
+	iclk = &pll->clks[0];
+	iclk->pll = pll;
+	iclk->name = node->name;
+
+	init.name = node->name;
+	init.ops = &iproc_pll_ops;
+	init.flags = 0;
+	parent_name = of_clk_get_parent_name(node, 0);
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+	iclk->hw.init = &init;
+
+	if (vco) {
+		pll->num_vco_entries = num_vco_entries;
+		pll->vco_param = vco;
+	}
+
+	iproc_pll_sw_cfg(pll);
+
+	clk = clk_register(NULL, &iclk->hw);
+	if (WARN_ON(IS_ERR(clk)))
+		goto err_pll_register;
+
+	pll->clk_data.clks[0] = clk;
+
+	/* now initialize and register all leaf clocks */
+	for (i = 1; i < num_clks; i++) {
+		const char *clk_name;
+
+		memset(&init, 0, sizeof(init));
+		parent_name = node->name;
+
+		clk_name = kzalloc(IPROC_CLK_NAME_LEN, GFP_KERNEL);
+		if (WARN_ON(!clk_name))
+			goto err_clk_register;
+
+		ret = of_property_read_string_index(node, "clock-output-names",
+						    i, &clk_name);
+		if (WARN_ON(ret))
+			goto err_clk_register;
+
+		iclk = &pll->clks[i];
+		iclk->name = clk_name;
+		iclk->pll = pll;
+		iclk->ctrl = &clk_ctrl[i];
+
+		init.name = clk_name;
+		init.ops = &iproc_clk_ops;
+		init.flags = 0;
+		init.parent_names = (parent_name ? &parent_name : NULL);
+		init.num_parents = (parent_name ? 1 : 0);
+		iclk->hw.init = &init;
+
+		clk = clk_register(NULL, &iclk->hw);
+		if (WARN_ON(IS_ERR(clk)))
+			goto err_clk_register;
+
+		pll->clk_data.clks[i] = clk;
+	}
+
+	ret = of_clk_add_provider(node, of_clk_src_onecell_get, &pll->clk_data);
+	if (WARN_ON(ret))
+		goto err_clk_register;
+
+	return;
+
+err_clk_register:
+	for (i = 0; i < num_clks; i++) {
+		kfree(pll->clks[i].name);
+		clk_unregister(pll->clk_data.clks[i]);
+	}
+
+err_pll_register:
+	if (pll->asiu_base)
+		iounmap(pll->asiu_base);
+
+err_asiu_iomap:
+	iounmap(pll->pwr_base);
+
+err_pwr_iomap:
+	iounmap(pll->pll_base);
+
+err_pll_iomap:
+	kfree(pll->clks);
+
+err_clks:
+	kfree(pll->clk_data.clks);
+
+err_clk_data:
+	kfree(pll);
+}
diff --git a/drivers/clk/bcm/clk-iproc.h b/drivers/clk/bcm/clk-iproc.h
new file mode 100644
index 000000000000..d834b7abd5c6
--- /dev/null
+++ b/drivers/clk/bcm/clk-iproc.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2014 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CLK_IPROC_H
+#define _CLK_IPROC_H
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/clk-provider.h>
+
+#define IPROC_CLK_NAME_LEN 25
+#define IPROC_CLK_INVALID_OFFSET 0xffffffff
+#define bit_mask(width) ((1 << (width)) - 1)
+
+/* clocks that should not be disabled at runtime */
+#define IPROC_CLK_AON BIT(0)
+
+/* PLL that requires gating through ASIU */
+#define IPROC_CLK_PLL_ASIU BIT(1)
+
+/* PLL that has fractional part of the NDIV */
+#define IPROC_CLK_PLL_HAS_NDIV_FRAC BIT(2)
+
+/*
+ * Some of the iProc PLL/clocks may have an ASIC bug that requires read back
+ * of the same register following the write to flush the write transaction into
+ * the intended register
+ */
+#define IPROC_CLK_NEEDS_READ_BACK BIT(3)
+
+/*
+ * Some PLLs require the PLL SW override bit to be set before changes can be
+ * applied to the PLL
+ */
+#define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4)
+
+/*
+ * Parameters for VCO frequency configuration
+ *
+ * VCO frequency =
+ * ((ndiv_int + ndiv_frac / 2^20) * (ref freqeuncy  / pdiv)
+ */
+struct iproc_pll_vco_param {
+	unsigned long rate;
+	unsigned int ndiv_int;
+	unsigned int ndiv_frac;
+	unsigned int pdiv;
+};
+
+struct iproc_clk_reg_op {
+	unsigned int offset;
+	unsigned int shift;
+	unsigned int width;
+};
+
+/*
+ * Clock gating control at the top ASIU level
+ */
+struct iproc_asiu_gate {
+	unsigned int offset;
+	unsigned int en_shift;
+};
+
+/*
+ * Control of powering on/off of a PLL
+ *
+ * Before powering off a PLL, input isolation (ISO) needs to be enabled
+ */
+struct iproc_pll_aon_pwr_ctrl {
+	unsigned int offset;
+	unsigned int pwr_width;
+	unsigned int pwr_shift;
+	unsigned int iso_shift;
+};
+
+/*
+ * Control of the PLL reset, with Ki, Kp, and Ka parameters
+ */
+struct iproc_pll_reset_ctrl {
+	unsigned int offset;
+	unsigned int reset_shift;
+	unsigned int p_reset_shift;
+	unsigned int ki_shift;
+	unsigned int ki_width;
+	unsigned int kp_shift;
+	unsigned int kp_width;
+	unsigned int ka_shift;
+	unsigned int ka_width;
+};
+
+/*
+ * To enable SW control of the PLL
+ */
+struct iproc_pll_sw_ctrl {
+	unsigned int offset;
+	unsigned int shift;
+};
+
+struct iproc_pll_vco_ctrl {
+	unsigned int u_offset;
+	unsigned int l_offset;
+};
+
+/*
+ * Main PLL control parameters
+ */
+struct iproc_pll_ctrl {
+	unsigned long flags;
+	struct iproc_pll_aon_pwr_ctrl aon;
+	struct iproc_asiu_gate asiu;
+	struct iproc_pll_reset_ctrl reset;
+	struct iproc_pll_sw_ctrl sw_ctrl;
+	struct iproc_clk_reg_op ndiv_int;
+	struct iproc_clk_reg_op ndiv_frac;
+	struct iproc_clk_reg_op pdiv;
+	struct iproc_pll_vco_ctrl vco_ctrl;
+	struct iproc_clk_reg_op status;
+};
+
+/*
+ * Controls enabling/disabling a PLL derived clock
+ */
+struct iproc_clk_enable_ctrl {
+	unsigned int offset;
+	unsigned int enable_shift;
+	unsigned int hold_shift;
+	unsigned int bypass_shift;
+};
+
+/*
+ * Main clock control parameters for clocks derived from the PLLs
+ */
+struct iproc_clk_ctrl {
+	unsigned int channel;
+	unsigned long flags;
+	struct iproc_clk_enable_ctrl enable;
+	struct iproc_clk_reg_op mdiv;
+};
+
+/*
+ * Divisor of the ASIU clocks
+ */
+struct iproc_asiu_div {
+	unsigned int offset;
+	unsigned int en_shift;
+	unsigned int high_shift;
+	unsigned int high_width;
+	unsigned int low_shift;
+	unsigned int low_width;
+};
+
+void __init iproc_armpll_setup(struct device_node *node);
+void __init iproc_pll_clk_setup(struct device_node *node,
+				const struct iproc_pll_ctrl *pll_ctrl,
+				const struct iproc_pll_vco_param *vco,
+				unsigned int num_vco_entries,
+				const struct iproc_clk_ctrl *clk_ctrl,
+				unsigned int num_clks);
+void __init iproc_asiu_setup(struct device_node *node,
+			     const struct iproc_asiu_div *div,
+			     const struct iproc_asiu_gate *gate,
+			     unsigned int num_clks);
+
+#endif /* _CLK_IPROC_H */

From 69a0b2c559099a043662f8c96214d8eab32a7153 Mon Sep 17 00:00:00 2001
From: Ray Jui <rjui@broadcom.com>
Date: Tue, 5 May 2015 11:13:20 -0700
Subject: [PATCH 120/135] clk: Change bcm clocks build dependency

The clock code under drivers/clk/bcm now contains code for both the
Broadcom mobile SoCs and the iProc SoCs. Change the the makefile
dependency to be under config flag CONFIG_ARCH_BCM that's enabled for
both families of SoCs

Signed-off-by: Ray Jui <rjui@broadcom.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 drivers/clk/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 3233f0e8bf43..d4bc8ed29984 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -46,7 +46,7 @@ obj-$(CONFIG_COMMON_CLK_WM831X)		+= clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_XGENE)		+= clk-xgene.o
 obj-$(CONFIG_COMMON_CLK_PWM)		+= clk-pwm.o
 obj-$(CONFIG_COMMON_CLK_AT91)		+= at91/
-obj-$(CONFIG_ARCH_BCM_MOBILE)		+= bcm/
+obj-$(CONFIG_ARCH_BCM)			+= bcm/
 obj-$(CONFIG_ARCH_BERLIN)		+= berlin/
 obj-$(CONFIG_ARCH_HISI)			+= hisilicon/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/

From 61ca7b0c7fffb968bd16394daf05b7e888e9541e Mon Sep 17 00:00:00 2001
From: Ray Jui <rjui@broadcom.com>
Date: Tue, 5 May 2015 11:13:21 -0700
Subject: [PATCH 121/135] clk: cygnus: add clock support for Broadcom Cygnus

The Broadcom Cygnus SoC is architected under the iProc architecture. It
has the following PLLs: ARMPLL, GENPLL, LCPLL0, MIPIPLL, all dervied
from an onboard crystal. Cygnus also has various ASIU clocks that are
derived directly from the onboard crystal.

Signed-off-by: Ray Jui <rjui@broadcom.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 drivers/clk/bcm/Makefile               |   1 +
 drivers/clk/bcm/clk-cygnus.c           | 265 +++++++++++++++++++++++++
 include/dt-bindings/clock/bcm-cygnus.h |  68 +++++++
 3 files changed, 334 insertions(+)
 create mode 100644 drivers/clk/bcm/clk-cygnus.c
 create mode 100644 include/dt-bindings/clock/bcm-cygnus.h

diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile
index 0facbbc5652c..8a7a477862c7 100644
--- a/drivers/clk/bcm/Makefile
+++ b/drivers/clk/bcm/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_CLK_BCM_KONA)	+= clk-kona-setup.o
 obj-$(CONFIG_CLK_BCM_KONA)	+= clk-bcm281xx.o
 obj-$(CONFIG_CLK_BCM_KONA)	+= clk-bcm21664.o
 obj-$(CONFIG_COMMON_CLK_IPROC)	+= clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o
+obj-$(CONFIG_ARCH_BCM_CYGNUS)	+= clk-cygnus.o
diff --git a/drivers/clk/bcm/clk-cygnus.c b/drivers/clk/bcm/clk-cygnus.c
new file mode 100644
index 000000000000..316c60337661
--- /dev/null
+++ b/drivers/clk/bcm/clk-cygnus.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2014 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/clkdev.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+
+#include <dt-bindings/clock/bcm-cygnus.h>
+#include "clk-iproc.h"
+
+#define reg_val(o, s, w) { .offset = o, .shift = s, .width = w, }
+
+#define aon_val(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
+	.pwr_shift = ps, .iso_shift = is }
+
+#define sw_ctrl_val(o, s) { .offset = o, .shift = s, }
+
+#define asiu_div_val(o, es, hs, hw, ls, lw) \
+		{ .offset = o, .en_shift = es, .high_shift = hs, \
+		.high_width = hw, .low_shift = ls, .low_width = lw }
+
+#define reset_val(o, rs, prs, kis, kiw, kps, kpw, kas, kaw) { .offset = o, \
+	.reset_shift = rs, .p_reset_shift = prs, .ki_shift = kis, \
+	.ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
+	.ka_width = kaw }
+
+#define vco_ctrl_val(uo, lo) { .u_offset = uo, .l_offset = lo }
+
+#define enable_val(o, es, hs, bs) { .offset = o, .enable_shift = es, \
+	.hold_shift = hs, .bypass_shift = bs }
+
+#define asiu_gate_val(o, es) { .offset = o, .en_shift = es }
+
+static void __init cygnus_armpll_init(struct device_node *node)
+{
+	iproc_armpll_setup(node);
+}
+CLK_OF_DECLARE(cygnus_armpll, "brcm,cygnus-armpll", cygnus_armpll_init);
+
+static const struct iproc_pll_ctrl genpll = {
+	.flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
+		IPROC_CLK_PLL_NEEDS_SW_CFG,
+	.aon = aon_val(0x0, 2, 1, 0),
+	.reset = reset_val(0x0, 11, 10, 4, 3, 0, 4, 7, 3),
+	.sw_ctrl = sw_ctrl_val(0x10, 31),
+	.ndiv_int = reg_val(0x10, 20, 10),
+	.ndiv_frac = reg_val(0x10, 0, 20),
+	.pdiv = reg_val(0x14, 0, 4),
+	.vco_ctrl = vco_ctrl_val(0x18, 0x1c),
+	.status = reg_val(0x28, 12, 1),
+};
+
+static const struct iproc_clk_ctrl genpll_clk[] = {
+	[BCM_CYGNUS_GENPLL_AXI21_CLK] = {
+		.channel = BCM_CYGNUS_GENPLL_AXI21_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = enable_val(0x4, 6, 0, 12),
+		.mdiv = reg_val(0x20, 0, 8),
+	},
+	[BCM_CYGNUS_GENPLL_250MHZ_CLK] = {
+		.channel = BCM_CYGNUS_GENPLL_250MHZ_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = enable_val(0x4, 7, 1, 13),
+		.mdiv = reg_val(0x20, 10, 8),
+	},
+	[BCM_CYGNUS_GENPLL_IHOST_SYS_CLK] = {
+		.channel = BCM_CYGNUS_GENPLL_IHOST_SYS_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = enable_val(0x4, 8, 2, 14),
+		.mdiv = reg_val(0x20, 20, 8),
+	},
+	[BCM_CYGNUS_GENPLL_ENET_SW_CLK] = {
+		.channel = BCM_CYGNUS_GENPLL_ENET_SW_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = enable_val(0x4, 9, 3, 15),
+		.mdiv = reg_val(0x24, 0, 8),
+	},
+	[BCM_CYGNUS_GENPLL_AUDIO_125_CLK] = {
+		.channel = BCM_CYGNUS_GENPLL_AUDIO_125_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = enable_val(0x4, 10, 4, 16),
+		.mdiv = reg_val(0x24, 10, 8),
+	},
+	[BCM_CYGNUS_GENPLL_CAN_CLK] = {
+		.channel = BCM_CYGNUS_GENPLL_CAN_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = enable_val(0x4, 11, 5, 17),
+		.mdiv = reg_val(0x24, 20, 8),
+	},
+};
+
+static void __init cygnus_genpll_clk_init(struct device_node *node)
+{
+	iproc_pll_clk_setup(node, &genpll, NULL, 0, genpll_clk,
+			    ARRAY_SIZE(genpll_clk));
+}
+CLK_OF_DECLARE(cygnus_genpll, "brcm,cygnus-genpll", cygnus_genpll_clk_init);
+
+static const struct iproc_pll_ctrl lcpll0 = {
+	.flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
+	.aon = aon_val(0x0, 2, 5, 4),
+	.reset = reset_val(0x0, 31, 30, 27, 3, 23, 4, 19, 4),
+	.sw_ctrl = sw_ctrl_val(0x4, 31),
+	.ndiv_int = reg_val(0x4, 16, 10),
+	.pdiv = reg_val(0x4, 26, 4),
+	.vco_ctrl = vco_ctrl_val(0x10, 0x14),
+	.status = reg_val(0x18, 12, 1),
+};
+
+static const struct iproc_clk_ctrl lcpll0_clk[] = {
+	[BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK] = {
+		.channel = BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = enable_val(0x0, 7, 1, 13),
+		.mdiv = reg_val(0x8, 0, 8),
+	},
+	[BCM_CYGNUS_LCPLL0_DDR_PHY_CLK] = {
+		.channel = BCM_CYGNUS_LCPLL0_DDR_PHY_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = enable_val(0x0, 8, 2, 14),
+		.mdiv = reg_val(0x8, 10, 8),
+	},
+	[BCM_CYGNUS_LCPLL0_SDIO_CLK] = {
+		.channel = BCM_CYGNUS_LCPLL0_SDIO_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = enable_val(0x0, 9, 3, 15),
+		.mdiv = reg_val(0x8, 20, 8),
+	},
+	[BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK] = {
+		.channel = BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = enable_val(0x0, 10, 4, 16),
+		.mdiv = reg_val(0xc, 0, 8),
+	},
+	[BCM_CYGNUS_LCPLL0_SMART_CARD_CLK] = {
+		.channel = BCM_CYGNUS_LCPLL0_SMART_CARD_CLK,
+		.flags = IPROC_CLK_AON,
+		.enable = enable_val(0x0, 11, 5, 17),
+		.mdiv = reg_val(0xc, 10, 8),
+	},
+	[BCM_CYGNUS_LCPLL0_CH5_UNUSED] = {
+		.channel = BCM_CYGNUS_LCPLL0_CH5_UNUSED,
+		.flags = IPROC_CLK_AON,
+		.enable = enable_val(0x0, 12, 6, 18),
+		.mdiv = reg_val(0xc, 20, 8),
+	},
+};
+
+static void __init cygnus_lcpll0_clk_init(struct device_node *node)
+{
+	iproc_pll_clk_setup(node, &lcpll0, NULL, 0, lcpll0_clk,
+			    ARRAY_SIZE(lcpll0_clk));
+}
+CLK_OF_DECLARE(cygnus_lcpll0, "brcm,cygnus-lcpll0", cygnus_lcpll0_clk_init);
+
+/*
+ * MIPI PLL VCO frequency parameter table
+ */
+static const struct iproc_pll_vco_param mipipll_vco_params[] = {
+	/* rate (Hz) ndiv_int ndiv_frac pdiv */
+	{ 750000000UL,   30,     0,        1 },
+	{ 1000000000UL,  40,     0,        1 },
+	{ 1350000000ul,  54,     0,        1 },
+	{ 2000000000UL,  80,     0,        1 },
+	{ 2100000000UL,  84,     0,        1 },
+	{ 2250000000UL,  90,     0,        1 },
+	{ 2500000000UL,  100,    0,        1 },
+	{ 2700000000UL,  54,     0,        0 },
+	{ 2975000000UL,  119,    0,        1 },
+	{ 3100000000UL,  124,    0,        1 },
+	{ 3150000000UL,  126,    0,        1 },
+};
+
+static const struct iproc_pll_ctrl mipipll = {
+	.flags = IPROC_CLK_PLL_ASIU | IPROC_CLK_PLL_HAS_NDIV_FRAC |
+		 IPROC_CLK_NEEDS_READ_BACK,
+	.aon = aon_val(0x0, 4, 17, 16),
+	.asiu = asiu_gate_val(0x0, 3),
+	.reset = reset_val(0x0, 11, 10, 4, 3, 0, 4, 7, 4),
+	.ndiv_int = reg_val(0x10, 20, 10),
+	.ndiv_frac = reg_val(0x10, 0, 20),
+	.pdiv = reg_val(0x14, 0, 4),
+	.vco_ctrl = vco_ctrl_val(0x18, 0x1c),
+	.status = reg_val(0x28, 12, 1),
+};
+
+static const struct iproc_clk_ctrl mipipll_clk[] = {
+	[BCM_CYGNUS_MIPIPLL_CH0_UNUSED] = {
+		.channel = BCM_CYGNUS_MIPIPLL_CH0_UNUSED,
+		.flags = IPROC_CLK_NEEDS_READ_BACK,
+		.enable = enable_val(0x4, 12, 6, 18),
+		.mdiv = reg_val(0x20, 0, 8),
+	},
+	[BCM_CYGNUS_MIPIPLL_CH1_LCD] = {
+		.channel = BCM_CYGNUS_MIPIPLL_CH1_LCD,
+		.flags = IPROC_CLK_NEEDS_READ_BACK,
+		.enable = enable_val(0x4, 13, 7, 19),
+		.mdiv = reg_val(0x20, 10, 8),
+	},
+	[BCM_CYGNUS_MIPIPLL_CH2_V3D] = {
+		.channel = BCM_CYGNUS_MIPIPLL_CH2_V3D,
+		.flags = IPROC_CLK_NEEDS_READ_BACK,
+		.enable = enable_val(0x4, 14, 8, 20),
+		.mdiv = reg_val(0x20, 20, 8),
+	},
+	[BCM_CYGNUS_MIPIPLL_CH3_UNUSED] = {
+		.channel = BCM_CYGNUS_MIPIPLL_CH3_UNUSED,
+		.flags = IPROC_CLK_NEEDS_READ_BACK,
+		.enable = enable_val(0x4, 15, 9, 21),
+		.mdiv = reg_val(0x24, 0, 8),
+	},
+	[BCM_CYGNUS_MIPIPLL_CH4_UNUSED] = {
+		.channel = BCM_CYGNUS_MIPIPLL_CH4_UNUSED,
+		.flags = IPROC_CLK_NEEDS_READ_BACK,
+		.enable = enable_val(0x4, 16, 10, 22),
+		.mdiv = reg_val(0x24, 10, 8),
+	},
+	[BCM_CYGNUS_MIPIPLL_CH5_UNUSED] = {
+		.channel = BCM_CYGNUS_MIPIPLL_CH5_UNUSED,
+		.flags = IPROC_CLK_NEEDS_READ_BACK,
+		.enable = enable_val(0x4, 17, 11, 23),
+		.mdiv = reg_val(0x24, 20, 8),
+	},
+};
+
+static void __init cygnus_mipipll_clk_init(struct device_node *node)
+{
+	iproc_pll_clk_setup(node, &mipipll, mipipll_vco_params,
+			    ARRAY_SIZE(mipipll_vco_params), mipipll_clk,
+			    ARRAY_SIZE(mipipll_clk));
+}
+CLK_OF_DECLARE(cygnus_mipipll, "brcm,cygnus-mipipll", cygnus_mipipll_clk_init);
+
+static const struct iproc_asiu_div asiu_div[] = {
+	[BCM_CYGNUS_ASIU_KEYPAD_CLK] = asiu_div_val(0x0, 31, 16, 10, 0, 10),
+	[BCM_CYGNUS_ASIU_ADC_CLK] = asiu_div_val(0x4, 31, 16, 10, 0, 10),
+	[BCM_CYGNUS_ASIU_PWM_CLK] = asiu_div_val(0x8, 31, 16, 10, 0, 10),
+};
+
+static const struct iproc_asiu_gate asiu_gate[] = {
+	[BCM_CYGNUS_ASIU_KEYPAD_CLK] = asiu_gate_val(0x0, 7),
+	[BCM_CYGNUS_ASIU_ADC_CLK] = asiu_gate_val(0x0, 9),
+	[BCM_CYGNUS_ASIU_PWM_CLK] = asiu_gate_val(IPROC_CLK_INVALID_OFFSET, 0),
+};
+
+static void __init cygnus_asiu_init(struct device_node *node)
+{
+	iproc_asiu_setup(node, asiu_div, asiu_gate, ARRAY_SIZE(asiu_div));
+}
+CLK_OF_DECLARE(cygnus_asiu_clk, "brcm,cygnus-asiu-clk", cygnus_asiu_init);
diff --git a/include/dt-bindings/clock/bcm-cygnus.h b/include/dt-bindings/clock/bcm-cygnus.h
new file mode 100644
index 000000000000..32fbc475087a
--- /dev/null
+++ b/include/dt-bindings/clock/bcm-cygnus.h
@@ -0,0 +1,68 @@
+/*
+ *  BSD LICENSE
+ *
+ *  Copyright(c) 2014 Broadcom Corporation.  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in
+ *      the documentation and/or other materials provided with the
+ *      distribution.
+ *    * Neither the name of Broadcom Corporation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CLOCK_BCM_CYGNUS_H
+#define _CLOCK_BCM_CYGNUS_H
+
+/* GENPLL clock ID */
+#define BCM_CYGNUS_GENPLL                     0
+#define BCM_CYGNUS_GENPLL_AXI21_CLK           1
+#define BCM_CYGNUS_GENPLL_250MHZ_CLK          2
+#define BCM_CYGNUS_GENPLL_IHOST_SYS_CLK       3
+#define BCM_CYGNUS_GENPLL_ENET_SW_CLK         4
+#define BCM_CYGNUS_GENPLL_AUDIO_125_CLK       5
+#define BCM_CYGNUS_GENPLL_CAN_CLK             6
+
+/* LCPLL0 clock ID */
+#define BCM_CYGNUS_LCPLL0                     0
+#define BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK    1
+#define BCM_CYGNUS_LCPLL0_DDR_PHY_CLK         2
+#define BCM_CYGNUS_LCPLL0_SDIO_CLK            3
+#define BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK     4
+#define BCM_CYGNUS_LCPLL0_SMART_CARD_CLK      5
+#define BCM_CYGNUS_LCPLL0_CH5_UNUSED          6
+
+/* MIPI PLL clock ID */
+#define BCM_CYGNUS_MIPIPLL                    0
+#define BCM_CYGNUS_MIPIPLL_CH0_UNUSED         1
+#define BCM_CYGNUS_MIPIPLL_CH1_LCD            2
+#define BCM_CYGNUS_MIPIPLL_CH2_V3D            3
+#define BCM_CYGNUS_MIPIPLL_CH3_UNUSED         4
+#define BCM_CYGNUS_MIPIPLL_CH4_UNUSED         5
+#define BCM_CYGNUS_MIPIPLL_CH5_UNUSED         6
+
+/* ASIU clock ID */
+#define BCM_CYGNUS_ASIU_KEYPAD_CLK    0
+#define BCM_CYGNUS_ASIU_ADC_CLK       1
+#define BCM_CYGNUS_ASIU_PWM_CLK       2
+
+#endif /* _CLOCK_BCM_CYGNUS_H */

From d0b30c983f0e3793193a96697e59cfaaba594501 Mon Sep 17 00:00:00 2001
From: Ray Jui <rjui@broadcom.com>
Date: Tue, 5 May 2015 11:13:23 -0700
Subject: [PATCH 122/135] clk: cygnus: remove Cygnus dummy clock binding

Remove old Cygnus dummy clock binding document, as it's replaced by
Documentation/devicetree/bindings/clock/brcm,iproc-clocks.txt

Signed-off-by: Ray Jui <rjui@broadcom.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 .../bindings/clock/bcm-cygnus-clock.txt       | 34 -------------------
 1 file changed, 34 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/clock/bcm-cygnus-clock.txt

diff --git a/Documentation/devicetree/bindings/clock/bcm-cygnus-clock.txt b/Documentation/devicetree/bindings/clock/bcm-cygnus-clock.txt
deleted file mode 100644
index 00d26edec8bc..000000000000
--- a/Documentation/devicetree/bindings/clock/bcm-cygnus-clock.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-Broadcom Cygnus Clocks
-
-This binding uses the common clock binding:
-Documentation/devicetree/bindings/clock/clock-bindings.txt
-
-Currently various "fixed" clocks are declared for peripheral drivers that use
-the common clock framework to reference their core clocks. Proper support of
-these clocks will be added later
-
-Device tree example:
-
-	clocks {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-
-		osc: oscillator {
-			compatible = "fixed-clock";
-			#clock-cells = <1>;
-			clock-frequency = <25000000>;
-		};
-
-		apb_clk: apb_clk {
-			compatible = "fixed-clock";
-			#clock-cells = <0>;
-			clock-frequency = <1000000000>;
-		};
-
-		periph_clk: periph_clk {
-			compatible = "fixed-clock";
-			#clock-cells = <0>;
-			clock-frequency = <500000000>;
-		};
-	};

From dc627eea98b1e12f9ff2ecd241a34a2056fdddbd Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon@free-electrons.com>
Date: Tue, 16 Jun 2015 17:56:19 +0200
Subject: [PATCH 123/135] clk: mvebu: flag the crypto clk as CLK_IGNORE_UNUSED

The crypto SRAM, used by the armada 370 cpuidle code to workaround a bug
in the BootROM code, requires the crypto clk to be up and running.
Flag the crypto clk as IGNORE_UNUSED until we add the proper
infrastructure to define the crypto SRAM in the DT and reference the crypto
clk in this SRAM node.

Reported-by: Kevin Hilman <khilman@linaro.org>
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Tested-by: Kevin Hilman <khilman@linaro.org>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 drivers/clk/mvebu/armada-370.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/mvebu/armada-370.c b/drivers/clk/mvebu/armada-370.c
index c19fd77e6c27..2c7c1085f883 100644
--- a/drivers/clk/mvebu/armada-370.c
+++ b/drivers/clk/mvebu/armada-370.c
@@ -163,7 +163,7 @@ static const struct clk_gating_soc_desc a370_gating_desc[] __initconst = {
 	{ "pex1", "pex1_en", 9, 0 },
 	{ "sata0", NULL, 15, 0 },
 	{ "sdio", NULL, 17, 0 },
-	{ "crypto", NULL, 23, 0 },
+	{ "crypto", NULL, 23, CLK_IGNORE_UNUSED },
 	{ "tdm", NULL, 25, 0 },
 	{ "ddr", NULL, 28, CLK_IGNORE_UNUSED },
 	{ "sata1", NULL, 30, 0 },

From 02fdfd708fd252a778709beb6c65d5e7360341ac Mon Sep 17 00:00:00 2001
From: Murali Karicheri <m-karicheri2@ti.com>
Date: Fri, 29 May 2015 12:04:12 -0400
Subject: [PATCH 124/135] clk: keystone: add support for post divider register
 for main pll

Main PLL controller has post divider bits in a separate register in
pll controller. Use the value from this register instead of fixed
divider when available.

Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 .../bindings/clock/keystone-pll.txt           |  8 ++++----
 drivers/clk/keystone/pll.c                    | 20 +++++++++++++++++--
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/clock/keystone-pll.txt b/Documentation/devicetree/bindings/clock/keystone-pll.txt
index 225990f79b7c..47570d207215 100644
--- a/Documentation/devicetree/bindings/clock/keystone-pll.txt
+++ b/Documentation/devicetree/bindings/clock/keystone-pll.txt
@@ -15,8 +15,8 @@ Required properties:
 - compatible : shall be "ti,keystone,main-pll-clock" or "ti,keystone,pll-clock"
 - clocks : parent clock phandle
 - reg - pll control0 and pll multipler registers
-- reg-names : control and multiplier. The multiplier is applicable only for
-		main pll clock
+- reg-names : control, multiplier and post-divider. The multiplier and
+		post-divider registers are applicable only for main pll clock
 - fixed-postdiv : fixed post divider value. If absent, use clkod register bits
 		for postdiv
 
@@ -25,8 +25,8 @@ Example:
 		#clock-cells = <0>;
 		compatible = "ti,keystone,main-pll-clock";
 		clocks = <&refclksys>;
-		reg = <0x02620350 4>, <0x02310110 4>;
-		reg-names = "control", "multiplier";
+		reg = <0x02620350 4>, <0x02310110 4>, <0x02310108 4>;
+		reg-names = "control", "multiplier", "post-divider";
 		fixed-postdiv = <2>;
 	};
 
diff --git a/drivers/clk/keystone/pll.c b/drivers/clk/keystone/pll.c
index 0dd8a4b12747..4a375ead70e9 100644
--- a/drivers/clk/keystone/pll.c
+++ b/drivers/clk/keystone/pll.c
@@ -37,7 +37,8 @@
  *	Main PLL or any other PLLs in the device such as ARM PLL, DDR PLL
  *	or PA PLL available on keystone2. These PLLs are controlled by
  *	this register. Main PLL is controlled by a PLL controller.
- * @pllm: PLL register map address
+ * @pllm: PLL register map address for multiplier bits
+ * @pllod: PLL register map address for post divider bits
  * @pll_ctl0: PLL controller map address
  * @pllm_lower_mask: multiplier lower mask
  * @pllm_upper_mask: multiplier upper mask
@@ -53,6 +54,7 @@ struct clk_pll_data {
 	u32 phy_pllm;
 	u32 phy_pll_ctl0;
 	void __iomem *pllm;
+	void __iomem *pllod;
 	void __iomem *pll_ctl0;
 	u32 pllm_lower_mask;
 	u32 pllm_upper_mask;
@@ -102,7 +104,11 @@ static unsigned long clk_pllclk_recalc(struct clk_hw *hw,
 		/* read post divider from od bits*/
 		postdiv = ((val & pll_data->clkod_mask) >>
 				 pll_data->clkod_shift) + 1;
-	else
+	else if (pll_data->pllod) {
+		postdiv = readl(pll_data->pllod);
+		postdiv = ((postdiv & pll_data->clkod_mask) >>
+				pll_data->clkod_shift) + 1;
+	} else
 		postdiv = pll_data->postdiv;
 
 	rate /= (prediv + 1);
@@ -172,12 +178,21 @@ static void __init _of_pll_clk_init(struct device_node *node, bool pllctrl)
 		/* assume the PLL has output divider register bits */
 		pll_data->clkod_mask = CLKOD_MASK;
 		pll_data->clkod_shift = CLKOD_SHIFT;
+
+		/*
+		 * Check if there is an post-divider register. If not
+		 * assume od bits are part of control register.
+		 */
+		i = of_property_match_string(node, "reg-names",
+					     "post-divider");
+		pll_data->pllod = of_iomap(node, i);
 	}
 
 	i = of_property_match_string(node, "reg-names", "control");
 	pll_data->pll_ctl0 = of_iomap(node, i);
 	if (!pll_data->pll_ctl0) {
 		pr_err("%s: ioremap failed\n", __func__);
+		iounmap(pll_data->pllod);
 		goto out;
 	}
 
@@ -193,6 +208,7 @@ static void __init _of_pll_clk_init(struct device_node *node, bool pllctrl)
 		pll_data->pllm = of_iomap(node, i);
 		if (!pll_data->pllm) {
 			iounmap(pll_data->pll_ctl0);
+			iounmap(pll_data->pllod);
 			goto out;
 		}
 	}

From b04e0b8fd5443b61c04e6103f16c5d1e1821e295 Mon Sep 17 00:00:00 2001
From: Joachim Eastwood <manabian@gmail.com>
Date: Thu, 28 May 2015 22:31:43 +0200
Subject: [PATCH 125/135] clk: add lpc18xx cgu clk driver

Add driver for NXP LPC18xx/43xx Clock Generation Unit (CGU). The CGU
contains several clock generators and output stages that route the
clocks either directly to peripherals or to a Clock Control Unit
(CCU).

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 drivers/clk/Makefile                    |   1 +
 drivers/clk/nxp/Makefile                |   1 +
 drivers/clk/nxp/clk-lpc18xx-cgu.c       | 635 ++++++++++++++++++++++++
 include/dt-bindings/clock/lpc18xx-cgu.h |  41 ++
 4 files changed, 678 insertions(+)
 create mode 100644 drivers/clk/nxp/Makefile
 create mode 100644 drivers/clk/nxp/clk-lpc18xx-cgu.c
 create mode 100644 include/dt-bindings/clock/lpc18xx-cgu.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d4bc8ed29984..256977ed050a 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -57,6 +57,7 @@ endif
 obj-$(CONFIG_PLAT_ORION)		+= mvebu/
 obj-$(CONFIG_ARCH_MESON)		+= meson/
 obj-$(CONFIG_ARCH_MXS)			+= mxs/
+obj-$(CONFIG_ARCH_LPC18XX)		+= nxp/
 obj-$(CONFIG_MACH_PISTACHIO)		+= pistachio/
 obj-$(CONFIG_COMMON_CLK_PXA)		+= pxa/
 obj-$(CONFIG_COMMON_CLK_QCOM)		+= qcom/
diff --git a/drivers/clk/nxp/Makefile b/drivers/clk/nxp/Makefile
new file mode 100644
index 000000000000..aca9d3e4f7fe
--- /dev/null
+++ b/drivers/clk/nxp/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_LPC18XX)	+= clk-lpc18xx-cgu.o
diff --git a/drivers/clk/nxp/clk-lpc18xx-cgu.c b/drivers/clk/nxp/clk-lpc18xx-cgu.c
new file mode 100644
index 000000000000..81e9e1c788f4
--- /dev/null
+++ b/drivers/clk/nxp/clk-lpc18xx-cgu.c
@@ -0,0 +1,635 @@
+/*
+ * Clk driver for NXP LPC18xx/LPC43xx Clock Generation Unit (CGU)
+ *
+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <dt-bindings/clock/lpc18xx-cgu.h>
+
+/* Clock Generation Unit (CGU) registers */
+#define LPC18XX_CGU_XTAL_OSC_CTRL	0x018
+#define LPC18XX_CGU_PLL0USB_STAT	0x01c
+#define LPC18XX_CGU_PLL0USB_CTRL	0x020
+#define LPC18XX_CGU_PLL0USB_MDIV	0x024
+#define LPC18XX_CGU_PLL0USB_NP_DIV	0x028
+#define LPC18XX_CGU_PLL0AUDIO_STAT	0x02c
+#define LPC18XX_CGU_PLL0AUDIO_CTRL	0x030
+#define LPC18XX_CGU_PLL0AUDIO_MDIV	0x034
+#define LPC18XX_CGU_PLL0AUDIO_NP_DIV	0x038
+#define LPC18XX_CGU_PLL0AUDIO_FRAC	0x03c
+#define LPC18XX_CGU_PLL1_STAT		0x040
+#define LPC18XX_CGU_PLL1_CTRL		0x044
+#define  LPC18XX_PLL1_CTRL_FBSEL	BIT(6)
+#define  LPC18XX_PLL1_CTRL_DIRECT	BIT(7)
+#define LPC18XX_CGU_IDIV_CTRL(n)	(0x048 + (n) * sizeof(u32))
+#define LPC18XX_CGU_BASE_CLK(id)	(0x05c + (id) * sizeof(u32))
+#define LPC18XX_CGU_PLL_CTRL_OFFSET	0x4
+
+/* PLL0 bits common to both audio and USB PLL */
+#define LPC18XX_PLL0_STAT_LOCK		BIT(0)
+#define LPC18XX_PLL0_CTRL_PD		BIT(0)
+#define LPC18XX_PLL0_CTRL_BYPASS	BIT(1)
+#define LPC18XX_PLL0_CTRL_DIRECTI	BIT(2)
+#define LPC18XX_PLL0_CTRL_DIRECTO	BIT(3)
+#define LPC18XX_PLL0_CTRL_CLKEN		BIT(4)
+#define LPC18XX_PLL0_MDIV_MDEC_MASK	0x1ffff
+#define LPC18XX_PLL0_MDIV_SELP_SHIFT	17
+#define LPC18XX_PLL0_MDIV_SELI_SHIFT	22
+#define LPC18XX_PLL0_MSEL_MAX		BIT(15)
+
+/* Register value that gives PLL0 post/pre dividers equal to 1 */
+#define LPC18XX_PLL0_NP_DIVS_1		0x00302062
+
+enum {
+	CLK_SRC_OSC32,
+	CLK_SRC_IRC,
+	CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK,
+	CLK_SRC_GP_CLKIN,
+	CLK_SRC_RESERVED1,
+	CLK_SRC_OSC,
+	CLK_SRC_PLL0USB,
+	CLK_SRC_PLL0AUDIO,
+	CLK_SRC_PLL1,
+	CLK_SRC_RESERVED2,
+	CLK_SRC_RESERVED3,
+	CLK_SRC_IDIVA,
+	CLK_SRC_IDIVB,
+	CLK_SRC_IDIVC,
+	CLK_SRC_IDIVD,
+	CLK_SRC_IDIVE,
+	CLK_SRC_MAX
+};
+
+static const char *clk_src_names[CLK_SRC_MAX] = {
+	[CLK_SRC_OSC32]		= "osc32",
+	[CLK_SRC_IRC]		= "irc",
+	[CLK_SRC_ENET_RX_CLK]	= "enet_rx_clk",
+	[CLK_SRC_ENET_TX_CLK]	= "enet_tx_clk",
+	[CLK_SRC_GP_CLKIN]	= "gp_clkin",
+	[CLK_SRC_OSC]		= "osc",
+	[CLK_SRC_PLL0USB]	= "pll0usb",
+	[CLK_SRC_PLL0AUDIO]	= "pll0audio",
+	[CLK_SRC_PLL1]		= "pll1",
+	[CLK_SRC_IDIVA]		= "idiva",
+	[CLK_SRC_IDIVB]		= "idivb",
+	[CLK_SRC_IDIVC]		= "idivc",
+	[CLK_SRC_IDIVD]		= "idivd",
+	[CLK_SRC_IDIVE]		= "idive",
+};
+
+static const char *clk_base_names[BASE_CLK_MAX] = {
+	[BASE_SAFE_CLK]		= "base_safe_clk",
+	[BASE_USB0_CLK]		= "base_usb0_clk",
+	[BASE_PERIPH_CLK]	= "base_periph_clk",
+	[BASE_USB1_CLK]		= "base_usb1_clk",
+	[BASE_CPU_CLK]		= "base_cpu_clk",
+	[BASE_SPIFI_CLK]	= "base_spifi_clk",
+	[BASE_SPI_CLK]		= "base_spi_clk",
+	[BASE_PHY_RX_CLK]	= "base_phy_rx_clk",
+	[BASE_PHY_TX_CLK]	= "base_phy_tx_clk",
+	[BASE_APB1_CLK]		= "base_apb1_clk",
+	[BASE_APB3_CLK]		= "base_apb3_clk",
+	[BASE_LCD_CLK]		= "base_lcd_clk",
+	[BASE_ADCHS_CLK]	= "base_adchs_clk",
+	[BASE_SDIO_CLK]		= "base_sdio_clk",
+	[BASE_SSP0_CLK]		= "base_ssp0_clk",
+	[BASE_SSP1_CLK]		= "base_ssp1_clk",
+	[BASE_UART0_CLK]	= "base_uart0_clk",
+	[BASE_UART1_CLK]	= "base_uart1_clk",
+	[BASE_UART2_CLK]	= "base_uart2_clk",
+	[BASE_UART3_CLK]	= "base_uart3_clk",
+	[BASE_OUT_CLK]		= "base_out_clk",
+	[BASE_AUDIO_CLK]	= "base_audio_clk",
+	[BASE_CGU_OUT0_CLK]	= "base_cgu_out0_clk",
+	[BASE_CGU_OUT1_CLK]	= "base_cgu_out1_clk",
+};
+
+static u32 lpc18xx_cgu_pll0_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL1, CLK_SRC_IDIVA, CLK_SRC_IDIVB, CLK_SRC_IDIVC,
+	CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+static u32 lpc18xx_cgu_pll1_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_IDIVA,
+	CLK_SRC_IDIVB, CLK_SRC_IDIVC, CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+static u32 lpc18xx_cgu_idiva_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1
+};
+
+static u32 lpc18xx_cgu_idivbcde_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1, CLK_SRC_IDIVA,
+};
+
+static u32 lpc18xx_cgu_base_irc_src_ids[] = {CLK_SRC_IRC};
+
+static u32 lpc18xx_cgu_base_usb0_src_ids[] = {CLK_SRC_PLL0USB};
+
+static u32 lpc18xx_cgu_base_common_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1, CLK_SRC_IDIVA,
+	CLK_SRC_IDIVB, CLK_SRC_IDIVC, CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+static u32 lpc18xx_cgu_base_all_src_ids[] = {
+	CLK_SRC_OSC32, CLK_SRC_IRC, CLK_SRC_ENET_RX_CLK,
+	CLK_SRC_ENET_TX_CLK, CLK_SRC_GP_CLKIN, CLK_SRC_OSC,
+	CLK_SRC_PLL0USB, CLK_SRC_PLL0AUDIO, CLK_SRC_PLL1,
+	CLK_SRC_IDIVA, CLK_SRC_IDIVB, CLK_SRC_IDIVC,
+	CLK_SRC_IDIVD, CLK_SRC_IDIVE,
+};
+
+struct lpc18xx_cgu_src_clk_div {
+	u8 clk_id;
+	u8 n_parents;
+	struct clk_divider	div;
+	struct clk_mux		mux;
+	struct clk_gate		gate;
+};
+
+#define LPC1XX_CGU_SRC_CLK_DIV(_id, _width, _table)	\
+{							\
+	.clk_id = CLK_SRC_ ##_id,			\
+	.n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table),	\
+	.div = {					\
+		.shift = 2,				\
+		.width = _width,			\
+	},						\
+	.mux = {					\
+		.mask = 0x1f,				\
+		.shift = 24,				\
+		.table = lpc18xx_cgu_ ##_table,		\
+	},						\
+	.gate = {					\
+		.bit_idx = 0,				\
+		.flags = CLK_GATE_SET_TO_DISABLE,	\
+	},						\
+}
+
+static struct lpc18xx_cgu_src_clk_div lpc18xx_cgu_src_clk_divs[] = {
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVA, 2, idiva_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVB, 4, idivbcde_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVC, 4, idivbcde_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVD, 4, idivbcde_src_ids),
+	LPC1XX_CGU_SRC_CLK_DIV(IDIVE, 8, idivbcde_src_ids),
+};
+
+struct lpc18xx_cgu_base_clk {
+	u8 clk_id;
+	u8 n_parents;
+	struct clk_mux mux;
+	struct clk_gate gate;
+};
+
+#define LPC1XX_CGU_BASE_CLK(_id, _table, _flags)	\
+{							\
+	.clk_id = BASE_ ##_id ##_CLK,			\
+	.n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table),	\
+	.mux = {					\
+		.mask = 0x1f,				\
+		.shift = 24,				\
+		.table = lpc18xx_cgu_ ##_table,		\
+		.flags = _flags,			\
+	},						\
+	.gate = {					\
+		.bit_idx = 0,				\
+		.flags = CLK_GATE_SET_TO_DISABLE,	\
+	},						\
+}
+
+static struct lpc18xx_cgu_base_clk lpc18xx_cgu_base_clks[] = {
+	LPC1XX_CGU_BASE_CLK(SAFE,	base_irc_src_ids, CLK_MUX_READ_ONLY),
+	LPC1XX_CGU_BASE_CLK(USB0,	base_usb0_src_ids,   0),
+	LPC1XX_CGU_BASE_CLK(PERIPH,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(USB1,	base_all_src_ids,    0),
+	LPC1XX_CGU_BASE_CLK(CPU,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SPIFI,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SPI,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(PHY_RX,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(PHY_TX,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(APB1,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(APB3,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(LCD,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(ADCHS,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SDIO,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SSP0,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(SSP1,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART0,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART1,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART2,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(UART3,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(OUT,	base_all_src_ids,    0),
+	{ /* 21 reserved */ },
+	{ /* 22 reserved */ },
+	{ /* 23 reserved */ },
+	{ /* 24 reserved */ },
+	LPC1XX_CGU_BASE_CLK(AUDIO,	base_common_src_ids, 0),
+	LPC1XX_CGU_BASE_CLK(CGU_OUT0,	base_all_src_ids,    0),
+	LPC1XX_CGU_BASE_CLK(CGU_OUT1,	base_all_src_ids,    0),
+};
+
+struct lpc18xx_pll {
+	struct		clk_hw hw;
+	void __iomem	*reg;
+	spinlock_t	*lock;
+	u8		flags;
+};
+
+#define to_lpc_pll(hw) container_of(hw, struct lpc18xx_pll, hw)
+
+struct lpc18xx_cgu_pll_clk {
+	u8 clk_id;
+	u8 n_parents;
+	u8 reg_offset;
+	struct clk_mux mux;
+	struct clk_gate gate;
+	struct lpc18xx_pll pll;
+	const struct clk_ops *pll_ops;
+};
+
+#define LPC1XX_CGU_CLK_PLL(_id, _table, _pll_ops)	\
+{							\
+	.clk_id = CLK_SRC_ ##_id,			\
+	.n_parents = ARRAY_SIZE(lpc18xx_cgu_ ##_table),	\
+	.reg_offset = LPC18XX_CGU_ ##_id ##_STAT,	\
+	.mux = {					\
+		.mask = 0x1f,				\
+		.shift = 24,				\
+		.table = lpc18xx_cgu_ ##_table,		\
+	},						\
+	.gate = {					\
+		.bit_idx = 0,				\
+		.flags = CLK_GATE_SET_TO_DISABLE,	\
+	},						\
+	.pll_ops = &lpc18xx_ ##_pll_ops,		\
+}
+
+/*
+ * PLL0 uses a special register value encoding. The compute functions below
+ * are taken or derived from the LPC1850 user manual (section 12.6.3.3).
+ */
+
+/* Compute PLL0 multiplier from decoded version */
+static u32 lpc18xx_pll0_mdec2msel(u32 x)
+{
+	int i;
+
+	switch (x) {
+	case 0x18003: return 1;
+	case 0x10003: return 2;
+	default:
+		for (i = LPC18XX_PLL0_MSEL_MAX + 1; x != 0x4000 && i > 0; i--)
+			x = ((x ^ x >> 14) & 1) | (x << 1 & 0x7fff);
+		return i;
+	}
+}
+/* Compute PLL0 decoded multiplier from binary version */
+static u32 lpc18xx_pll0_msel2mdec(u32 msel)
+{
+	u32 i, x = 0x4000;
+
+	switch (msel) {
+	case 0: return 0;
+	case 1: return 0x18003;
+	case 2: return 0x10003;
+	default:
+		for (i = msel; i <= LPC18XX_PLL0_MSEL_MAX; i++)
+			x = ((x ^ x >> 1) & 1) << 14 | (x >> 1 & 0xffff);
+		return x;
+	}
+}
+
+/* Compute PLL0 bandwidth SELI reg from multiplier */
+static u32 lpc18xx_pll0_msel2seli(u32 msel)
+{
+	u32 tmp;
+
+	if (msel > 16384) return 1;
+	if (msel >  8192) return 2;
+	if (msel >  2048) return 4;
+	if (msel >=  501) return 8;
+	if (msel >=   60) {
+		tmp = 1024 / (msel + 9);
+		return ((1024 == (tmp * (msel + 9))) == 0) ? tmp * 4 : (tmp + 1) * 4;
+	}
+
+	return (msel & 0x3c) + 4;
+}
+
+/* Compute PLL0 bandwidth SELP reg from multiplier */
+static u32 lpc18xx_pll0_msel2selp(u32 msel)
+{
+	if (msel < 60)
+		return (msel >> 1) + 1;
+
+	return 31;
+}
+
+static unsigned long lpc18xx_pll0_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	struct lpc18xx_pll *pll = to_lpc_pll(hw);
+	u32 ctrl, mdiv, msel, npdiv;
+
+	ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+	mdiv = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_MDIV);
+	npdiv = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_NP_DIV);
+
+	if (ctrl & LPC18XX_PLL0_CTRL_BYPASS)
+		return parent_rate;
+
+	if (npdiv != LPC18XX_PLL0_NP_DIVS_1) {
+		pr_warn("%s: pre/post dividers not supported\n", __func__);
+		return 0;
+	}
+
+	msel = lpc18xx_pll0_mdec2msel(mdiv & LPC18XX_PLL0_MDIV_MDEC_MASK);
+	if (msel)
+		return 2 * msel * parent_rate;
+
+	pr_warn("%s: unable to calculate rate\n", __func__);
+
+	return 0;
+}
+
+static long lpc18xx_pll0_round_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *prate)
+{
+	unsigned long m;
+
+	if (*prate < rate) {
+		pr_warn("%s: pll dividers not supported\n", __func__);
+		return -EINVAL;
+	}
+
+	m = DIV_ROUND_UP_ULL(*prate, rate * 2);
+	if (m <= 0 && m > LPC18XX_PLL0_MSEL_MAX) {
+		pr_warn("%s: unable to support rate %lu\n", __func__, rate);
+		return -EINVAL;
+	}
+
+	return 2 * *prate * m;
+}
+
+static int lpc18xx_pll0_set_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	struct lpc18xx_pll *pll = to_lpc_pll(hw);
+	u32 ctrl, stat, m;
+	int retry = 3;
+
+	if (parent_rate < rate) {
+		pr_warn("%s: pll dividers not supported\n", __func__);
+		return -EINVAL;
+	}
+
+	m = DIV_ROUND_UP_ULL(parent_rate, rate * 2);
+	if (m <= 0 && m > LPC18XX_PLL0_MSEL_MAX) {
+		pr_warn("%s: unable to support rate %lu\n", __func__, rate);
+		return -EINVAL;
+	}
+
+	m  = lpc18xx_pll0_msel2mdec(m);
+	m |= lpc18xx_pll0_msel2selp(m) << LPC18XX_PLL0_MDIV_SELP_SHIFT;
+	m |= lpc18xx_pll0_msel2seli(m) << LPC18XX_PLL0_MDIV_SELI_SHIFT;
+
+	/* Power down PLL, disable clk output and dividers */
+	ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+	ctrl |= LPC18XX_PLL0_CTRL_PD;
+	ctrl &= ~(LPC18XX_PLL0_CTRL_BYPASS | LPC18XX_PLL0_CTRL_DIRECTI |
+		  LPC18XX_PLL0_CTRL_DIRECTO | LPC18XX_PLL0_CTRL_CLKEN);
+	clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+
+	/* Configure new PLL settings */
+	clk_writel(m, pll->reg + LPC18XX_CGU_PLL0USB_MDIV);
+	clk_writel(LPC18XX_PLL0_NP_DIVS_1, pll->reg + LPC18XX_CGU_PLL0USB_NP_DIV);
+
+	/* Power up PLL and wait for lock */
+	ctrl &= ~LPC18XX_PLL0_CTRL_PD;
+	clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+	do {
+		udelay(10);
+		stat = clk_readl(pll->reg + LPC18XX_CGU_PLL0USB_STAT);
+		if (stat & LPC18XX_PLL0_STAT_LOCK) {
+			ctrl |= LPC18XX_PLL0_CTRL_CLKEN;
+			clk_writel(ctrl, pll->reg + LPC18XX_CGU_PLL0USB_CTRL);
+
+			return 0;
+		}
+	} while (retry--);
+
+	pr_warn("%s: unable to lock pll\n", __func__);
+
+	return -EINVAL;
+}
+
+static const struct clk_ops lpc18xx_pll0_ops = {
+	.recalc_rate	= lpc18xx_pll0_recalc_rate,
+	.round_rate	= lpc18xx_pll0_round_rate,
+	.set_rate	= lpc18xx_pll0_set_rate,
+};
+
+static unsigned long lpc18xx_pll1_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	struct lpc18xx_pll *pll = to_lpc_pll(hw);
+	u16 msel, nsel, psel;
+	bool direct, fbsel;
+	u32 stat, ctrl;
+
+	stat = clk_readl(pll->reg + LPC18XX_CGU_PLL1_STAT);
+	ctrl = clk_readl(pll->reg + LPC18XX_CGU_PLL1_CTRL);
+
+	direct = (ctrl & LPC18XX_PLL1_CTRL_DIRECT) ? true : false;
+	fbsel = (ctrl & LPC18XX_PLL1_CTRL_FBSEL) ? true : false;
+
+	msel = ((ctrl >> 16) & 0xff) + 1;
+	nsel = ((ctrl >> 12) & 0x3) + 1;
+
+	if (direct || fbsel)
+		return msel * (parent_rate / nsel);
+
+	psel = (ctrl >>  8) & 0x3;
+	psel = 1 << psel;
+
+	return (msel / (2 * psel)) * (parent_rate / nsel);
+}
+
+static const struct clk_ops lpc18xx_pll1_ops = {
+	.recalc_rate = lpc18xx_pll1_recalc_rate,
+};
+
+static struct lpc18xx_cgu_pll_clk lpc18xx_cgu_src_clk_plls[] = {
+	LPC1XX_CGU_CLK_PLL(PLL0USB,	pll0_src_ids, pll0_ops),
+	LPC1XX_CGU_CLK_PLL(PLL0AUDIO,	pll0_src_ids, pll0_ops),
+	LPC1XX_CGU_CLK_PLL(PLL1,	pll1_src_ids, pll1_ops),
+};
+
+static void lpc18xx_fill_parent_names(const char **parent, u32 *id, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		parent[i] = clk_src_names[id[i]];
+}
+
+static struct clk *lpc18xx_cgu_register_div(struct lpc18xx_cgu_src_clk_div *clk,
+					    void __iomem *base, int n)
+{
+	void __iomem *reg = base + LPC18XX_CGU_IDIV_CTRL(n);
+	const char *name = clk_src_names[clk->clk_id];
+	const char *parents[CLK_SRC_MAX];
+
+	clk->div.reg = reg;
+	clk->mux.reg = reg;
+	clk->gate.reg = reg;
+
+	lpc18xx_fill_parent_names(parents, clk->mux.table, clk->n_parents);
+
+	return clk_register_composite(NULL, name, parents, clk->n_parents,
+				      &clk->mux.hw, &clk_mux_ops,
+				      &clk->div.hw, &clk_divider_ops,
+				      &clk->gate.hw, &clk_gate_ops, 0);
+}
+
+
+static struct clk *lpc18xx_register_base_clk(struct lpc18xx_cgu_base_clk *clk,
+					     void __iomem *reg_base, int n)
+{
+	void __iomem *reg = reg_base + LPC18XX_CGU_BASE_CLK(n);
+	const char *name = clk_base_names[clk->clk_id];
+	const char *parents[CLK_SRC_MAX];
+
+	if (clk->n_parents == 0)
+		return ERR_PTR(-ENOENT);
+
+	clk->mux.reg = reg;
+	clk->gate.reg = reg;
+
+	lpc18xx_fill_parent_names(parents, clk->mux.table, clk->n_parents);
+
+	/* SAFE_CLK can not be turned off */
+	if (n == BASE_SAFE_CLK)
+		return clk_register_composite(NULL, name, parents, clk->n_parents,
+					      &clk->mux.hw, &clk_mux_ops,
+					      NULL, NULL, NULL, NULL, 0);
+
+	return clk_register_composite(NULL, name, parents, clk->n_parents,
+				      &clk->mux.hw, &clk_mux_ops,
+				      NULL,  NULL,
+				      &clk->gate.hw, &clk_gate_ops, 0);
+}
+
+
+static struct clk *lpc18xx_cgu_register_pll(struct lpc18xx_cgu_pll_clk *clk,
+					    void __iomem *base)
+{
+	const char *name = clk_src_names[clk->clk_id];
+	const char *parents[CLK_SRC_MAX];
+
+	clk->pll.reg  = base;
+	clk->mux.reg  = base + clk->reg_offset + LPC18XX_CGU_PLL_CTRL_OFFSET;
+	clk->gate.reg = base + clk->reg_offset + LPC18XX_CGU_PLL_CTRL_OFFSET;
+
+	lpc18xx_fill_parent_names(parents, clk->mux.table, clk->n_parents);
+
+	return clk_register_composite(NULL, name, parents, clk->n_parents,
+				      &clk->mux.hw, &clk_mux_ops,
+				      &clk->pll.hw, clk->pll_ops,
+				      &clk->gate.hw, &clk_gate_ops, 0);
+}
+
+static void __init lpc18xx_cgu_register_source_clks(struct device_node *np,
+						    void __iomem *base)
+{
+	const char *parents[CLK_SRC_MAX];
+	struct clk *clk;
+	int i;
+
+	/* Register the internal 12 MHz RC oscillator (IRC) */
+	clk = clk_register_fixed_rate(NULL, clk_src_names[CLK_SRC_IRC],
+				      NULL, CLK_IS_ROOT, 12000000);
+	if (IS_ERR(clk))
+		pr_warn("%s: failed to register irc clk\n", __func__);
+
+	/* Register crystal oscillator controlller */
+	parents[0] = of_clk_get_parent_name(np, 0);
+	clk = clk_register_gate(NULL, clk_src_names[CLK_SRC_OSC], parents[0],
+				0, base + LPC18XX_CGU_XTAL_OSC_CTRL,
+				0, CLK_GATE_SET_TO_DISABLE, NULL);
+	if (IS_ERR(clk))
+		pr_warn("%s: failed to register osc clk\n", __func__);
+
+	/* Register all PLLs */
+	for (i = 0; i < ARRAY_SIZE(lpc18xx_cgu_src_clk_plls); i++) {
+		clk = lpc18xx_cgu_register_pll(&lpc18xx_cgu_src_clk_plls[i],
+						   base);
+		if (IS_ERR(clk))
+			pr_warn("%s: failed to register pll (%d)\n", __func__, i);
+	}
+
+	/* Register all clock dividers A-E */
+	for (i = 0; i < ARRAY_SIZE(lpc18xx_cgu_src_clk_divs); i++) {
+		clk = lpc18xx_cgu_register_div(&lpc18xx_cgu_src_clk_divs[i],
+					       base, i);
+		if (IS_ERR(clk))
+			pr_warn("%s: failed to register div %d\n", __func__, i);
+	}
+}
+
+static struct clk *clk_base[BASE_CLK_MAX];
+static struct clk_onecell_data clk_base_data = {
+	.clks = clk_base,
+	.clk_num = BASE_CLK_MAX,
+};
+
+static void __init lpc18xx_cgu_register_base_clks(void __iomem *reg_base)
+{
+	int i;
+
+	for (i = BASE_SAFE_CLK; i < BASE_CLK_MAX; i++) {
+		clk_base[i] = lpc18xx_register_base_clk(&lpc18xx_cgu_base_clks[i],
+							reg_base, i);
+		if (IS_ERR(clk_base[i]) && PTR_ERR(clk_base[i]) != -ENOENT)
+			pr_warn("%s: register base clk %d failed\n", __func__, i);
+	}
+}
+
+static void __init lpc18xx_cgu_init(struct device_node *np)
+{
+	void __iomem *reg_base;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_warn("%s: failed to map address range\n", __func__);
+		return;
+	}
+
+	lpc18xx_cgu_register_source_clks(np, reg_base);
+	lpc18xx_cgu_register_base_clks(reg_base);
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_base_data);
+}
+CLK_OF_DECLARE(lpc18xx_cgu, "nxp,lpc1850-cgu", lpc18xx_cgu_init);
diff --git a/include/dt-bindings/clock/lpc18xx-cgu.h b/include/dt-bindings/clock/lpc18xx-cgu.h
new file mode 100644
index 000000000000..6e57c6d2ca66
--- /dev/null
+++ b/include/dt-bindings/clock/lpc18xx-cgu.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ */
+
+/* LPC18xx/43xx base clock ids */
+#define BASE_SAFE_CLK		0
+#define BASE_USB0_CLK		1
+#define BASE_PERIPH_CLK		2
+#define BASE_USB1_CLK		3
+#define BASE_CPU_CLK		4
+#define BASE_SPIFI_CLK		5
+#define BASE_SPI_CLK		6
+#define BASE_PHY_RX_CLK		7
+#define BASE_PHY_TX_CLK		8
+#define BASE_APB1_CLK		9
+#define BASE_APB3_CLK		10
+#define BASE_LCD_CLK		11
+#define BASE_ADCHS_CLK		12
+#define BASE_SDIO_CLK		13
+#define BASE_SSP0_CLK		14
+#define BASE_SSP1_CLK		15
+#define BASE_UART0_CLK		16
+#define BASE_UART1_CLK		17
+#define BASE_UART2_CLK		18
+#define BASE_UART3_CLK		19
+#define BASE_OUT_CLK		20
+#define BASE_RES1_CLK		21
+#define BASE_RES2_CLK		22
+#define BASE_RES3_CLK		23
+#define BASE_RES4_CLK		24
+#define BASE_AUDIO_CLK		25
+#define BASE_CGU_OUT0_CLK	26
+#define BASE_CGU_OUT1_CLK	27
+#define BASE_CLK_MAX		(BASE_CGU_OUT1_CLK + 1)

From 668c45df36939fbf0a3578ad97f547c8db86a7a0 Mon Sep 17 00:00:00 2001
From: Joachim Eastwood <manabian@gmail.com>
Date: Thu, 28 May 2015 22:31:44 +0200
Subject: [PATCH 126/135] doc: dt: add documentation for lpc1850-cgu clk driver

Add DT binding documentation for lpc1850-cgu driver.

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 .../devicetree/bindings/clock/lpc1850-cgu.txt | 131 ++++++++++++++++++
 1 file changed, 131 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-cgu.txt

diff --git a/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
new file mode 100644
index 000000000000..2cc32a9a945a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/lpc1850-cgu.txt
@@ -0,0 +1,131 @@
+* NXP LPC1850 Clock Generation Unit (CGU)
+
+The CGU generates multiple independent clocks for the core and the
+peripheral blocks of the LPC18xx. Each independent clock is called
+a base clock and itself is one of the inputs to the two Clock
+Control Units (CCUs) which control the branch clocks to the
+individual peripherals.
+
+The CGU selects the inputs to the clock generators from multiple
+clock sources, controls the clock generation, and routes the outputs
+of the clock generators through the clock source bus to the output
+stages. Each output stage provides an independent clock source and
+corresponds to one of the base clocks for the LPC18xx.
+
+ - Above text taken from NXP LPC1850 User Manual.
+
+
+This binding uses the common clock binding:
+    Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible:
+	Should be "nxp,lpc1850-cgu"
+- reg:
+	Shall define the base and range of the address space
+	containing clock control registers
+- #clock-cells:
+	Shall have value <1>.  The permitted clock-specifier values
+	are the base clock numbers defined below.
+- clocks:
+	Shall contain a list of phandles for the external input
+	sources to the CGU. The list shall be in the following
+	order: xtal, 32khz, enet_rx_clk, enet_tx_clk, gp_clkin.
+- clock-indices:
+	Shall be an ordered list of numbers defining the base clock
+	number provided by the CGU.
+- clock-output-names:
+	Shall be an ordered list of strings defining the names of
+	the clocks provided by the CGU.
+
+Which base clocks that are available on the CGU depends on the
+specific LPC part. Base clocks are numbered from 0 to 27.
+
+Number:		Name:			Description:
+ 0		BASE_SAFE_CLK		Base safe clock (always on) for WWDT
+ 1		BASE_USB0_CLK		Base clock for USB0
+ 2		BASE_PERIPH_CLK		Base clock for Cortex-M0SUB subsystem,
+					SPI, and SGPIO
+ 3		BASE_USB1_CLK		Base clock for USB1
+ 4		BASE_CPU_CLK		System base clock for ARM Cortex-M core
+					and APB peripheral blocks #0 and #2
+ 5		BASE_SPIFI_CLK		Base clock for SPIFI
+ 6		BASE_SPI_CLK		Base clock for SPI
+ 7		BASE_PHY_RX_CLK		Base clock for Ethernet PHY Receive clock
+ 8		BASE_PHY_TX_CLK		Base clock for Ethernet PHY Transmit clock
+ 9		BASE_APB1_CLK		Base clock for APB peripheral block # 1
+10		BASE_APB3_CLK		Base clock for APB peripheral block # 3
+11		BASE_LCD_CLK		Base clock for LCD
+12		BASE_ADCHS_CLK		Base clock for ADCHS
+13		BASE_SDIO_CLK		Base clock for SD/MMC
+14		BASE_SSP0_CLK		Base clock for SSP0
+15		BASE_SSP1_CLK		Base clock for SSP1
+16		BASE_UART0_CLK		Base clock for UART0
+17		BASE_UART1_CLK		Base clock for UART1
+18		BASE_UART2_CLK		Base clock for UART2
+19		BASE_UART3_CLK		Base clock for UART3
+20		BASE_OUT_CLK		Base clock for CLKOUT pin
+24-21		-			Reserved
+25		BASE_AUDIO_CLK		Base clock for audio system (I2S)
+26 		BASE_CGU_OUT0_CLK	Base clock for CGU_OUT0 clock output
+27 		BASE_CGU_OUT1_CLK	Base clock for CGU_OUT1 clock output
+
+BASE_PERIPH_CLK and BASE_SPI_CLK is only available on LPC43xx.
+BASE_ADCHS_CLK is only available on LPC4370.
+
+
+Example board file:
+
+/ {
+	clocks {
+		xtal: xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <12000000>;
+		};
+
+		xtal32: xtal32 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+
+		enet_rx_clk: enet_rx_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "enet_rx_clk";
+		};
+
+		enet_tx_clk: enet_tx_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "enet_tx_clk";
+		};
+
+		gp_clkin: gp_clkin {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <0>;
+			clock-output-names = "gp_clkin";
+		};
+	};
+
+	soc {
+		cgu: clock-controller@40050000 {
+			compatible = "nxp,lpc1850-cgu";
+			reg = <0x40050000 0x1000>;
+			#clock-cells = <1>;
+			clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>;
+		};
+
+		/* A CGU and CCU clock consumer */
+		lcdc: lcdc@40008000 {
+			...
+			clocks = <&cgu BASE_LCD_CLK>, <&ccu1 CLK_CPU_LCD>;
+			clock-names = "clcdclk", "apb_pclk";
+			...
+		};
+	};
+};

From 472cd304a36e0a1b21045ddc802ffb16a1cbac65 Mon Sep 17 00:00:00 2001
From: Joachim Eastwood <manabian@gmail.com>
Date: Thu, 28 May 2015 22:31:45 +0200
Subject: [PATCH 127/135] clk: add lpc18xx ccu clk driver

Add driver for NXP LPC18xx/43xx Clock Control Unit (CCU). The CCU
provides fine grained gating of most clocks present in the SoC.

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 drivers/clk/nxp/Makefile                |   1 +
 drivers/clk/nxp/clk-lpc18xx-ccu.c       | 293 ++++++++++++++++++++++++
 include/dt-bindings/clock/lpc18xx-ccu.h |  74 ++++++
 3 files changed, 368 insertions(+)
 create mode 100644 drivers/clk/nxp/clk-lpc18xx-ccu.c
 create mode 100644 include/dt-bindings/clock/lpc18xx-ccu.h

diff --git a/drivers/clk/nxp/Makefile b/drivers/clk/nxp/Makefile
index aca9d3e4f7fe..7f608b0ad7b4 100644
--- a/drivers/clk/nxp/Makefile
+++ b/drivers/clk/nxp/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ARCH_LPC18XX)	+= clk-lpc18xx-cgu.o
+obj-$(CONFIG_ARCH_LPC18XX)	+= clk-lpc18xx-ccu.o
diff --git a/drivers/clk/nxp/clk-lpc18xx-ccu.c b/drivers/clk/nxp/clk-lpc18xx-ccu.c
new file mode 100644
index 000000000000..eeaee97da110
--- /dev/null
+++ b/drivers/clk/nxp/clk-lpc18xx-ccu.c
@@ -0,0 +1,293 @@
+/*
+ * Clk driver for NXP LPC18xx/LPC43xx Clock Control Unit (CCU)
+ *
+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <dt-bindings/clock/lpc18xx-ccu.h>
+
+/* Bit defines for CCU branch configuration register */
+#define LPC18XX_CCU_RUN		BIT(0)
+#define LPC18XX_CCU_AUTO	BIT(1)
+#define LPC18XX_CCU_DIV		BIT(5)
+#define LPC18XX_CCU_DIVSTAT	BIT(27)
+
+/* CCU branch feature bits */
+#define CCU_BRANCH_IS_BUS	BIT(0)
+#define CCU_BRANCH_HAVE_DIV2	BIT(1)
+
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
+
+struct lpc18xx_branch_clk_data {
+	const char **name;
+	int num;
+};
+
+struct lpc18xx_clk_branch {
+	const char *base_name;
+	const char *name;
+	u16 offset;
+	u16 flags;
+	struct clk *clk;
+	struct clk_gate gate;
+};
+
+static struct lpc18xx_clk_branch clk_branches[] = {
+	{"base_apb3_clk", "apb3_bus",		CLK_APB3_BUS,		CCU_BRANCH_IS_BUS},
+	{"base_apb3_clk", "apb3_i2c1",		CLK_APB3_I2C1,		0},
+	{"base_apb3_clk", "apb3_dac",		CLK_APB3_DAC,		0},
+	{"base_apb3_clk", "apb3_adc0",		CLK_APB3_ADC0,		0},
+	{"base_apb3_clk", "apb3_adc1",		CLK_APB3_ADC1,		0},
+	{"base_apb3_clk", "apb3_can0",		CLK_APB3_CAN0,		0},
+
+	{"base_apb1_clk", "apb1_bus",		CLK_APB1_BUS,		CCU_BRANCH_IS_BUS},
+	{"base_apb1_clk", "apb1_mc_pwm",	CLK_APB1_MOTOCON_PWM,	0},
+	{"base_apb1_clk", "apb1_i2c0",		CLK_APB1_I2C0,		0},
+	{"base_apb1_clk", "apb1_i2s",		CLK_APB1_I2S,		0},
+	{"base_apb1_clk", "apb1_can1",		CLK_APB1_CAN1,		0},
+
+	{"base_spifi_clk", "spifi",		CLK_SPIFI,		0},
+
+	{"base_cpu_clk", "cpu_bus",		CLK_CPU_BUS,		CCU_BRANCH_IS_BUS},
+	{"base_cpu_clk", "cpu_spifi",		CLK_CPU_SPIFI,		0},
+	{"base_cpu_clk", "cpu_gpio",		CLK_CPU_GPIO,		0},
+	{"base_cpu_clk", "cpu_lcd",		CLK_CPU_LCD,		0},
+	{"base_cpu_clk", "cpu_ethernet",	CLK_CPU_ETHERNET,	0},
+	{"base_cpu_clk", "cpu_usb0",		CLK_CPU_USB0,		0},
+	{"base_cpu_clk", "cpu_emc",		CLK_CPU_EMC,		0},
+	{"base_cpu_clk", "cpu_sdio",		CLK_CPU_SDIO,		0},
+	{"base_cpu_clk", "cpu_dma",		CLK_CPU_DMA,		0},
+	{"base_cpu_clk", "cpu_core",		CLK_CPU_CORE,		0},
+	{"base_cpu_clk", "cpu_sct",		CLK_CPU_SCT,		0},
+	{"base_cpu_clk", "cpu_usb1",		CLK_CPU_USB1,		0},
+	{"base_cpu_clk", "cpu_emcdiv",		CLK_CPU_EMCDIV,		CCU_BRANCH_HAVE_DIV2},
+	{"base_cpu_clk", "cpu_flasha",		CLK_CPU_FLASHA,		CCU_BRANCH_HAVE_DIV2},
+	{"base_cpu_clk", "cpu_flashb",		CLK_CPU_FLASHB,		CCU_BRANCH_HAVE_DIV2},
+	{"base_cpu_clk", "cpu_m0app",		CLK_CPU_M0APP,		CCU_BRANCH_HAVE_DIV2},
+	{"base_cpu_clk", "cpu_adchs",		CLK_CPU_ADCHS,		CCU_BRANCH_HAVE_DIV2},
+	{"base_cpu_clk", "cpu_eeprom",		CLK_CPU_EEPROM,		CCU_BRANCH_HAVE_DIV2},
+	{"base_cpu_clk", "cpu_wwdt",		CLK_CPU_WWDT,		0},
+	{"base_cpu_clk", "cpu_uart0",		CLK_CPU_UART0,		0},
+	{"base_cpu_clk", "cpu_uart1",		CLK_CPU_UART1,		0},
+	{"base_cpu_clk", "cpu_ssp0",		CLK_CPU_SSP0,		0},
+	{"base_cpu_clk", "cpu_timer0",		CLK_CPU_TIMER0,		0},
+	{"base_cpu_clk", "cpu_timer1",		CLK_CPU_TIMER1,		0},
+	{"base_cpu_clk", "cpu_scu",		CLK_CPU_SCU,		0},
+	{"base_cpu_clk", "cpu_creg",		CLK_CPU_CREG,		0},
+	{"base_cpu_clk", "cpu_ritimer",		CLK_CPU_RITIMER,	0},
+	{"base_cpu_clk", "cpu_uart2",		CLK_CPU_UART2,		0},
+	{"base_cpu_clk", "cpu_uart3",		CLK_CPU_UART3,		0},
+	{"base_cpu_clk", "cpu_timer2",		CLK_CPU_TIMER2,		0},
+	{"base_cpu_clk", "cpu_timer3",		CLK_CPU_TIMER3,		0},
+	{"base_cpu_clk", "cpu_ssp1",		CLK_CPU_SSP1,		0},
+	{"base_cpu_clk", "cpu_qei",		CLK_CPU_QEI,		0},
+
+	{"base_periph_clk", "periph_bus",	CLK_PERIPH_BUS,		CCU_BRANCH_IS_BUS},
+	{"base_periph_clk", "periph_core",	CLK_PERIPH_CORE,	0},
+	{"base_periph_clk", "periph_sgpio",	CLK_PERIPH_SGPIO,	0},
+
+	{"base_usb0_clk",  "usb0",		CLK_USB0,		0},
+	{"base_usb1_clk",  "usb1",		CLK_USB1,		0},
+	{"base_spi_clk",   "spi",		CLK_SPI,		0},
+	{"base_adchs_clk", "adchs",		CLK_ADCHS,		0},
+
+	{"base_audio_clk", "audio",		CLK_AUDIO,		0},
+	{"base_uart3_clk", "apb2_uart3",	CLK_APB2_UART3,		0},
+	{"base_uart2_clk", "apb2_uart2",	CLK_APB2_UART2,		0},
+	{"base_uart1_clk", "apb0_uart1",	CLK_APB0_UART1,		0},
+	{"base_uart0_clk", "apb0_uart0",	CLK_APB0_UART0,		0},
+	{"base_ssp1_clk",  "apb2_ssp1",		CLK_APB2_SSP1,		0},
+	{"base_ssp0_clk",  "apb0_ssp0",		CLK_APB0_SSP0,		0},
+	{"base_sdio_clk",  "sdio",		CLK_SDIO,		0},
+};
+
+static struct clk *lpc18xx_ccu_branch_clk_get(struct of_phandle_args *clkspec,
+					      void *data)
+{
+	struct lpc18xx_branch_clk_data *clk_data = data;
+	unsigned int offset = clkspec->args[0];
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(clk_branches); i++) {
+		if (clk_branches[i].offset != offset)
+			continue;
+
+		for (j = 0; j < clk_data->num; j++) {
+			if (!strcmp(clk_branches[i].base_name, clk_data->name[j]))
+				return clk_branches[i].clk;
+		}
+	}
+
+	pr_err("%s: invalid clock offset %d\n", __func__, offset);
+
+	return ERR_PTR(-EINVAL);
+}
+
+static int lpc18xx_ccu_gate_endisable(struct clk_hw *hw, bool enable)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+	u32 val;
+
+	/*
+	 * Divider field is write only, so divider stat field must
+	 * be read so divider field can be set accordingly.
+	 */
+	val = clk_readl(gate->reg);
+	if (val & LPC18XX_CCU_DIVSTAT)
+		val |= LPC18XX_CCU_DIV;
+
+	if (enable) {
+		val |= LPC18XX_CCU_RUN;
+	} else {
+		/*
+		 * To safely disable a branch clock a squence of two separate
+		 * writes must be used. First write should set the AUTO bit
+		 * and the next write should clear the RUN bit.
+		 */
+		val |= LPC18XX_CCU_AUTO;
+		clk_writel(val, gate->reg);
+
+		val &= ~LPC18XX_CCU_RUN;
+	}
+
+	clk_writel(val, gate->reg);
+
+	return 0;
+}
+
+static int lpc18xx_ccu_gate_enable(struct clk_hw *hw)
+{
+	return lpc18xx_ccu_gate_endisable(hw, true);
+}
+
+static void lpc18xx_ccu_gate_disable(struct clk_hw *hw)
+{
+	lpc18xx_ccu_gate_endisable(hw, false);
+}
+
+static int lpc18xx_ccu_gate_is_enabled(struct clk_hw *hw)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+
+	return clk_readl(gate->reg) & LPC18XX_CCU_RUN;
+}
+
+static const struct clk_ops lpc18xx_ccu_gate_ops = {
+	.enable		= lpc18xx_ccu_gate_enable,
+	.disable	= lpc18xx_ccu_gate_disable,
+	.is_enabled	= lpc18xx_ccu_gate_is_enabled,
+};
+
+static void lpc18xx_ccu_register_branch_gate_div(struct lpc18xx_clk_branch *branch,
+						 void __iomem *reg_base,
+						 const char *parent)
+{
+	const struct clk_ops *div_ops = NULL;
+	struct clk_divider *div = NULL;
+	struct clk_hw *div_hw = NULL;
+
+	if (branch->flags & CCU_BRANCH_HAVE_DIV2) {
+		div = kzalloc(sizeof(*div), GFP_KERNEL);
+		if (!div)
+			return;
+
+		div->reg = branch->offset + reg_base;
+		div->flags = CLK_DIVIDER_READ_ONLY;
+		div->shift = 27;
+		div->width = 1;
+
+		div_hw = &div->hw;
+		div_ops = &clk_divider_ops;
+	}
+
+	branch->gate.reg = branch->offset + reg_base;
+	branch->gate.bit_idx = 0;
+
+	branch->clk = clk_register_composite(NULL, branch->name, &parent, 1,
+					     NULL, NULL,
+					     div_hw, div_ops,
+					     &branch->gate.hw, &lpc18xx_ccu_gate_ops, 0);
+	if (IS_ERR(branch->clk)) {
+		kfree(div);
+		pr_warn("%s: failed to register %s\n", __func__, branch->name);
+		return;
+	}
+
+	/* Grab essential branch clocks for CPU and SDRAM */
+	switch (branch->offset) {
+	case CLK_CPU_EMC:
+	case CLK_CPU_CORE:
+	case CLK_CPU_CREG:
+	case CLK_CPU_EMCDIV:
+		clk_prepare_enable(branch->clk);
+	}
+}
+
+static void lpc18xx_ccu_register_branch_clks(void __iomem *reg_base,
+					     const char *base_name)
+{
+	const char *parent = base_name;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(clk_branches); i++) {
+		if (strcmp(clk_branches[i].base_name, base_name))
+			continue;
+
+		lpc18xx_ccu_register_branch_gate_div(&clk_branches[i], reg_base,
+						     parent);
+
+		if (clk_branches[i].flags & CCU_BRANCH_IS_BUS)
+			parent = clk_branches[i].name;
+	}
+}
+
+static void __init lpc18xx_ccu_init(struct device_node *np)
+{
+	struct lpc18xx_branch_clk_data *clk_data;
+	void __iomem *reg_base;
+	int i, ret;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_warn("%s: failed to map address range\n", __func__);
+		return;
+	}
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return;
+
+	clk_data->num = of_property_count_strings(np, "clock-names");
+	clk_data->name = kcalloc(clk_data->num, sizeof(char *), GFP_KERNEL);
+	if (!clk_data->name) {
+		kfree(clk_data);
+		return;
+	}
+
+	for (i = 0; i < clk_data->num; i++) {
+		ret = of_property_read_string_index(np, "clock-names", i,
+						    &clk_data->name[i]);
+		if (ret) {
+			pr_warn("%s: failed to get clock name at idx %d\n",
+				__func__, i);
+			continue;
+		}
+
+		lpc18xx_ccu_register_branch_clks(reg_base, clk_data->name[i]);
+	}
+
+	of_clk_add_provider(np, lpc18xx_ccu_branch_clk_get, clk_data);
+}
+CLK_OF_DECLARE(lpc18xx_ccu, "nxp,lpc1850-ccu", lpc18xx_ccu_init);
diff --git a/include/dt-bindings/clock/lpc18xx-ccu.h b/include/dt-bindings/clock/lpc18xx-ccu.h
new file mode 100644
index 000000000000..bbfe00b6ab7d
--- /dev/null
+++ b/include/dt-bindings/clock/lpc18xx-ccu.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This code is released using a dual license strategy: BSD/GPL
+ * You can choose the licence that better fits your requirements.
+ *
+ * Released under the terms of 3-clause BSD License
+ * Released under the terms of GNU General Public License Version 2.0
+ *
+ */
+
+/* Clock Control Unit 1 (CCU1) clock offsets */
+#define CLK_APB3_BUS		0x100
+#define CLK_APB3_I2C1		0x108
+#define CLK_APB3_DAC		0x110
+#define CLK_APB3_ADC0		0x118
+#define CLK_APB3_ADC1		0x120
+#define CLK_APB3_CAN0		0x128
+#define CLK_APB1_BUS		0x200
+#define CLK_APB1_MOTOCON_PWM	0x208
+#define CLK_APB1_I2C0		0x210
+#define CLK_APB1_I2S		0x218
+#define CLK_APB1_CAN1		0x220
+#define CLK_SPIFI		0x300
+#define CLK_CPU_BUS		0x400
+#define CLK_CPU_SPIFI		0x408
+#define CLK_CPU_GPIO		0x410
+#define CLK_CPU_LCD		0x418
+#define CLK_CPU_ETHERNET	0x420
+#define CLK_CPU_USB0		0x428
+#define CLK_CPU_EMC		0x430
+#define CLK_CPU_SDIO		0x438
+#define CLK_CPU_DMA		0x440
+#define CLK_CPU_CORE		0x448
+#define CLK_CPU_SCT		0x468
+#define CLK_CPU_USB1		0x470
+#define CLK_CPU_EMCDIV		0x478
+#define CLK_CPU_FLASHA		0x480
+#define CLK_CPU_FLASHB		0x488
+#define CLK_CPU_M0APP		0x490
+#define CLK_CPU_ADCHS		0x498
+#define CLK_CPU_EEPROM		0x4a0
+#define CLK_CPU_WWDT		0x500
+#define CLK_CPU_UART0		0x508
+#define CLK_CPU_UART1		0x510
+#define CLK_CPU_SSP0		0x518
+#define CLK_CPU_TIMER0		0x520
+#define CLK_CPU_TIMER1		0x528
+#define CLK_CPU_SCU		0x530
+#define CLK_CPU_CREG		0x538
+#define CLK_CPU_RITIMER		0x600
+#define CLK_CPU_UART2		0x608
+#define CLK_CPU_UART3		0x610
+#define CLK_CPU_TIMER2		0x618
+#define CLK_CPU_TIMER3		0x620
+#define CLK_CPU_SSP1		0x628
+#define CLK_CPU_QEI		0x630
+#define CLK_PERIPH_BUS		0x700
+#define CLK_PERIPH_CORE		0x710
+#define CLK_PERIPH_SGPIO	0x718
+#define CLK_USB0		0x800
+#define CLK_USB1		0x900
+#define CLK_SPI			0xA00
+#define CLK_ADCHS		0xB00
+
+/* Clock Control Unit 2 (CCU2) clock offsets */
+#define CLK_AUDIO		0x100
+#define CLK_APB2_UART3		0x200
+#define CLK_APB2_UART2		0x300
+#define CLK_APB0_UART1		0x400
+#define CLK_APB0_UART0		0x500
+#define CLK_APB2_SSP1		0x600
+#define CLK_APB0_SSP0		0x700
+#define CLK_SDIO		0x800

From ddfb157444e3cdb6da18ea759730b4b4af65d3d9 Mon Sep 17 00:00:00 2001
From: Joachim Eastwood <manabian@gmail.com>
Date: Thu, 28 May 2015 22:31:46 +0200
Subject: [PATCH 128/135] doc: dt: add documentation for lpc1850-ccu clk driver

Add DT binding documentation for lpc1850-ccu clk driver.

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 .../devicetree/bindings/clock/lpc1850-ccu.txt | 77 +++++++++++++++++++
 1 file changed, 77 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/lpc1850-ccu.txt

diff --git a/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt b/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt
new file mode 100644
index 000000000000..fa97c12014ac
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/lpc1850-ccu.txt
@@ -0,0 +1,77 @@
+* NXP LPC1850 Clock Control Unit (CCU)
+
+Each CGU base clock has several clock branches which can be turned on
+or off independently by the Clock Control Units CCU1 or CCU2. The
+branch clocks are distributed between CCU1 and CCU2.
+
+ - Above text taken from NXP LPC1850 User Manual.
+
+This binding uses the common clock binding:
+    Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible:
+	Should be "nxp,lpc1850-ccu"
+- reg:
+	Shall define the base and range of the address space
+	containing clock control registers
+- #clock-cells:
+	Shall have value <1>.  The permitted clock-specifier values
+	are the branch clock names defined in table below.
+- clocks:
+	Shall contain a list of phandles for the base clocks routed
+	from the CGU to the specific CCU. See mapping of base clocks
+	and CCU in table below.
+- clock-names:
+	Shall contain a list of names for the base clock routed
+	from the CGU to the specific CCU. Valid CCU clock names:
+	"base_usb0_clk",  "base_periph_clk", "base_usb1_clk",
+	"base_cpu_clk",   "base_spifi_clk",  "base_spi_clk",
+	"base_apb1_clk",  "base_apb3_clk",   "base_adchs_clk",
+	"base_sdio_clk",  "base_ssp0_clk",   "base_ssp1_clk",
+	"base_uart0_clk", "base_uart1_clk",  "base_uart2_clk",
+	"base_uart3_clk", "base_audio_clk"
+
+Which branch clocks that are available on the CCU depends on the
+specific LPC part. Check the user manual for your specific part.
+
+A list of CCU clocks can be found in dt-bindings/clock/lpc18xx-ccu.h.
+
+Example board file:
+
+soc {
+	ccu1: clock-controller@40051000 {
+		compatible = "nxp,lpc1850-ccu";
+		reg = <0x40051000 0x1000>;
+		#clock-cells = <1>;
+		clocks = <&cgu BASE_APB3_CLK>,   <&cgu BASE_APB1_CLK>,
+			 <&cgu BASE_SPIFI_CLK>,  <&cgu BASE_CPU_CLK>,
+			 <&cgu BASE_PERIPH_CLK>, <&cgu BASE_USB0_CLK>,
+			 <&cgu BASE_USB1_CLK>,   <&cgu BASE_SPI_CLK>;
+		clock-names = "base_apb3_clk",   "base_apb1_clk",
+			      "base_spifi_clk",  "base_cpu_clk",
+			      "base_periph_clk", "base_usb0_clk",
+			      "base_usb1_clk",   "base_spi_clk";
+	};
+
+	ccu2: clock-controller@40052000 {
+		compatible = "nxp,lpc1850-ccu";
+		reg = <0x40052000 0x1000>;
+		#clock-cells = <1>;
+		clocks = <&cgu BASE_AUDIO_CLK>, <&cgu BASE_UART3_CLK>,
+			 <&cgu BASE_UART2_CLK>, <&cgu BASE_UART1_CLK>,
+			 <&cgu BASE_UART0_CLK>, <&cgu BASE_SSP1_CLK>,
+			 <&cgu BASE_SSP0_CLK>,  <&cgu BASE_SDIO_CLK>;
+		clock-names = "base_audio_clk", "base_uart3_clk",
+			      "base_uart2_clk", "base_uart1_clk",
+			      "base_uart0_clk", "base_ssp1_clk",
+			      "base_ssp0_clk",  "base_sdio_clk";
+	};
+
+	/* A user of CCU brach clocks */
+	uart1: serial@40082000 {
+		...
+		clocks = <&ccu2 CLK_APB0_UART1>, <&ccu1 CLK_CPU_UART1>;
+		...
+	};
+};

From d8d919879e9a645061a560a0a26abb9f3bca97df Mon Sep 17 00:00:00 2001
From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Date: Fri, 3 Apr 2015 18:43:44 +0200
Subject: [PATCH 129/135] clk: add CLK_RECALC_NEW_RATES clock flag for Exynos
 cpu clock support

This flag is needed to fix the issue with wrong dividers being setup
by Common Clock Framework when using the new Exynos cpu clock support.

The issue happens because clk_core_set_rate_nolock()  calls
clk_calc_new_rates(clk, rate) before both pre/post clock notifiers have
a chance to run.  In case of Exynos cpu clock support pre/post clock
notifiers are registered for mout_apll clock which is a parent of armclk
cpu clock and dividers are modified in both pre and post clock notifier.
This results in wrong dividers values being later programmed by
clk_change_rate(top).  To workaround the problem CLK_RECALC_NEW_RATES
flag is added and it is set for mout_apll clock later so the correct
divider values are re-calculated after both pre and post clock notifiers
had run.

For example when using "performance" governor on Exynos4210 Origen board
the cpufreq-dt driver requests to change the frequency from 1000MHz to
1200MHz and after the change state of the relevant clocks is following:

Without use of CLK_GET_RATE_NOCACHE flag:

 fout_apll rate: 1200000000
         fout_apll_div_2 rate: 600000000
                 mout_clkout_cpu rate: 600000000
                         div_clkout_cpu rate: 600000000
                                 clkout_cpu rate: 600000000
         mout_apll rate: 1200000000
                 armclk rate: 1200000000
                 mout_hpm rate: 1200000000
                         div_copy rate: 300000000
                                 div_hpm rate: 300000000
                 mout_core rate: 1200000000
                         div_core rate: 1200000000
                                 div_core2 rate: 1200000000
                                         arm_clk_div_2 rate: 600000000
                                         div_corem0 rate: 300000000
                                         div_corem1 rate: 150000000
                                         div_periph rate: 300000000
                         div_atb rate: 300000000
                                 div_pclk_dbg rate: 150000000
                 sclk_apll rate: 1200000000
                         sclk_apll_div_2 rate: 600000000

With use of CLK_GET_RATE_NOCACHE flag:

 fout_apll rate: 1200000000
         fout_apll_div_2 rate: 600000000
                 mout_clkout_cpu rate: 600000000
                         div_clkout_cpu rate: 600000000
                                 clkout_cpu rate: 600000000
         mout_apll rate: 1200000000
                 armclk rate: 1200000000
                 mout_hpm rate: 1200000000
                         div_copy rate: 200000000
                                 div_hpm rate: 200000000
                 mout_core rate: 1200000000
                         div_core rate: 1200000000
                                 div_core2 rate: 1200000000
                                         arm_clk_div_2 rate: 600000000
                                         div_corem0 rate: 300000000
                                         div_corem1 rate: 150000000
                                         div_periph rate: 300000000
                         div_atb rate: 240000000
                                 div_pclk_dbg rate: 120000000
                 sclk_apll rate: 150000000
                         sclk_apll_div_2 rate: 75000000

Without this change cpufreq-dt driver showed ~10 mA larger energy
consumption when compared to cpufreq-exynos one when "performance"
cpufreq governor was used on Exynos4210 SoC based Origen board.

This issue was probably meant to be workarounded by use of
CLK_GET_RATE_NOCACHE and CLK_DIVIDER_READ_ONLY clock flags in
the original Exynos cpu clock patchset (in "[PATCH v12 6/6] clk:
samsung: remove unused clock aliases and update clock flags" patch)
but usage of these flags is not sufficient to fix the issue observed.

Cc: Thomas Abraham <thomas.ab@samsung.com>
Cc: Tomasz Figa <tomasz.figa@gmail.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 drivers/clk/clk.c            | 3 +++
 include/linux/clk-provider.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 5b0f41868b42..0c0124c4eeeb 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1788,6 +1788,9 @@ static void clk_change_rate(struct clk_core *clk)
 	if (clk->notifier_count && old_rate != clk->rate)
 		__clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
 
+	if (clk->flags & CLK_RECALC_NEW_RATES)
+		(void)clk_calc_new_rates(clk, clk->new_rate);
+
 	/*
 	 * Use safe iteration, as change_rate can actually swap parents
 	 * for certain clock types.
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index df695313f975..82f59ca8188a 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -31,6 +31,7 @@
 #define CLK_GET_RATE_NOCACHE	BIT(6) /* do not use the cached clk rate */
 #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
 #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
+#define CLK_RECALC_NEW_RATES	BIT(9) /* recalc rates after notifications */
 
 struct clk_hw;
 struct clk_core;

From ddeac8d968d41d13a52582d6e80395a329e9b1ff Mon Sep 17 00:00:00 2001
From: Thomas Abraham <thomas.ab@samsung.com>
Date: Fri, 3 Apr 2015 18:43:45 +0200
Subject: [PATCH 130/135] clk: samsung: add infrastructure to register cpu
 clocks

The CPU clock provider supplies the clock to the CPU clock domain. The
composition and organization of the CPU clock provider could vary among
Exynos SoCs. A CPU clock provider can be composed of clock mux, dividers
and gates. This patch defines a new clock type for CPU clock provider and
adds infrastructure to register the CPU clock providers for Samsung
platforms.

Changes by Bartlomiej:
- fixed issue with setting lower dividers before the parent clock speed
  was lowered (the issue resulted in lockup on Exynos4210 SoC based
  Origen board when "ondemand" cpufreq governor was stress tested)
- fixed missing spin_unlock on error in exynos_cpuclk_post_rate_change()
  problem by moving cfg_data search outside of the spin locked area
- removed leftover kfree() in exynos_register_cpu_clock() that could
  result in dereferencing the NULL pointer on error
- moved spin_lock earlier in exynos_cpuclk_pre_rate_change() to cover
  reading of E4210_SRC_CPU and E4210_DIV_CPU1 registers
- added missing "last chance" checks to wait_until_divider_stable() and
  wait_until_mux_stable() (needed in case that IRQ handling took long
  time to proceed and resulted in function printing incorrect error
  message about timeout)
- moved E4210_CPU_DIV[0,1]() macros just before their only users,
  this resulted in moving them from patch #2 to patch #3/6 ("clk:
  samsung: exynos4: add cpu clock configuration data and instantiate
  cpu clock")
- removed E5250_CPU_DIV[0,1](), E5420_EGL_DIV0() and E5420_KFC_DIV()
  macros for now
- added my Copyrights to drivers/clk/samsung/clk-cpu.c

Cc: Tomasz Figa <tomasz.figa@gmail.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 drivers/clk/samsung/Makefile  |   2 +-
 drivers/clk/samsung/clk-cpu.c | 349 ++++++++++++++++++++++++++++++++++
 drivers/clk/samsung/clk-cpu.h |  73 +++++++
 3 files changed, 423 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/samsung/clk-cpu.c
 create mode 100644 drivers/clk/samsung/clk-cpu.h

diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index a17683b2cf27..5f6833ea355d 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -2,7 +2,7 @@
 # Samsung Clock specific Makefile
 #
 
-obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-pll.o
+obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-pll.o clk-cpu.o
 obj-$(CONFIG_SOC_EXYNOS3250)	+= clk-exynos3250.o
 obj-$(CONFIG_ARCH_EXYNOS4)	+= clk-exynos4.o
 obj-$(CONFIG_SOC_EXYNOS4415)	+= clk-exynos4415.o
diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c
new file mode 100644
index 000000000000..3a1fe07cfe9e
--- /dev/null
+++ b/drivers/clk/samsung/clk-cpu.c
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This file contains the utility function to register CPU clock for Samsung
+ * Exynos platforms. A CPU clock is defined as a clock supplied to a CPU or a
+ * group of CPUs. The CPU clock is typically derived from a hierarchy of clock
+ * blocks which includes mux and divider blocks. There are a number of other
+ * auxiliary clocks supplied to the CPU domain such as the debug blocks and AXI
+ * clock for CPU domain. The rates of these auxiliary clocks are related to the
+ * CPU clock rate and this relation is usually specified in the hardware manual
+ * of the SoC or supplied after the SoC characterization.
+ *
+ * The below implementation of the CPU clock allows the rate changes of the CPU
+ * clock and the corresponding rate changes of the auxillary clocks of the CPU
+ * domain. The platform clock driver provides a clock register configuration
+ * for each configurable rate which is then used to program the clock hardware
+ * registers to acheive a fast co-oridinated rate change for all the CPU domain
+ * clocks.
+ *
+ * On a rate change request for the CPU clock, the rate change is propagated
+ * upto the PLL supplying the clock to the CPU domain clock blocks. While the
+ * CPU domain PLL is reconfigured, the CPU domain clocks are driven using an
+ * alternate clock source. If required, the alternate clock source is divided
+ * down in order to keep the output clock rate within the previous OPP limits.
+*/
+
+#include <linux/errno.h>
+#include "clk-cpu.h"
+
+#define E4210_SRC_CPU		0x0
+#define E4210_STAT_CPU		0x200
+#define E4210_DIV_CPU0		0x300
+#define E4210_DIV_CPU1		0x304
+#define E4210_DIV_STAT_CPU0	0x400
+#define E4210_DIV_STAT_CPU1	0x404
+
+#define E4210_DIV0_RATIO0_MASK	0x7
+#define E4210_DIV1_HPM_MASK	(0x7 << 4)
+#define E4210_DIV1_COPY_MASK	(0x7 << 0)
+#define E4210_MUX_HPM_MASK	(1 << 20)
+#define E4210_DIV0_ATB_SHIFT	16
+#define E4210_DIV0_ATB_MASK	(DIV_MASK << E4210_DIV0_ATB_SHIFT)
+
+#define MAX_DIV			8
+#define DIV_MASK		7
+#define DIV_MASK_ALL		0xffffffff
+#define MUX_MASK		7
+
+/*
+ * Helper function to wait until divider(s) have stabilized after the divider
+ * value has changed.
+ */
+static void wait_until_divider_stable(void __iomem *div_reg, unsigned long mask)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(10);
+
+	do {
+		if (!(readl(div_reg) & mask))
+			return;
+	} while (time_before(jiffies, timeout));
+
+	if (!(readl(div_reg) & mask))
+		return;
+
+	pr_err("%s: timeout in divider stablization\n", __func__);
+}
+
+/*
+ * Helper function to wait until mux has stabilized after the mux selection
+ * value was changed.
+ */
+static void wait_until_mux_stable(void __iomem *mux_reg, u32 mux_pos,
+					unsigned long mux_value)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(10);
+
+	do {
+		if (((readl(mux_reg) >> mux_pos) & MUX_MASK) == mux_value)
+			return;
+	} while (time_before(jiffies, timeout));
+
+	if (((readl(mux_reg) >> mux_pos) & MUX_MASK) == mux_value)
+		return;
+
+	pr_err("%s: re-parenting mux timed-out\n", __func__);
+}
+
+/* common round rate callback useable for all types of CPU clocks */
+static long exynos_cpuclk_round_rate(struct clk_hw *hw,
+			unsigned long drate, unsigned long *prate)
+{
+	struct clk *parent = __clk_get_parent(hw->clk);
+	*prate = __clk_round_rate(parent, drate);
+	return *prate;
+}
+
+/* common recalc rate callback useable for all types of CPU clocks */
+static unsigned long exynos_cpuclk_recalc_rate(struct clk_hw *hw,
+			unsigned long parent_rate)
+{
+	/*
+	 * The CPU clock output (armclk) rate is the same as its parent
+	 * rate. Although there exist certain dividers inside the CPU
+	 * clock block that could be used to divide the parent clock,
+	 * the driver does not make use of them currently, except during
+	 * frequency transitions.
+	 */
+	return parent_rate;
+}
+
+static const struct clk_ops exynos_cpuclk_clk_ops = {
+	.recalc_rate = exynos_cpuclk_recalc_rate,
+	.round_rate = exynos_cpuclk_round_rate,
+};
+
+/*
+ * Helper function to set the 'safe' dividers for the CPU clock. The parameters
+ * div and mask contain the divider value and the register bit mask of the
+ * dividers to be programmed.
+ */
+static void exynos_set_safe_div(void __iomem *base, unsigned long div,
+					unsigned long mask)
+{
+	unsigned long div0;
+
+	div0 = readl(base + E4210_DIV_CPU0);
+	div0 = (div0 & ~mask) | (div & mask);
+	writel(div0, base + E4210_DIV_CPU0);
+	wait_until_divider_stable(base + E4210_DIV_STAT_CPU0, mask);
+}
+
+/* handler for pre-rate change notification from parent clock */
+static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
+			struct exynos_cpuclk *cpuclk, void __iomem *base)
+{
+	const struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg;
+	unsigned long alt_prate = clk_get_rate(cpuclk->alt_parent);
+	unsigned long alt_div = 0, alt_div_mask = DIV_MASK;
+	unsigned long div0, div1 = 0, mux_reg;
+
+	/* find out the divider values to use for clock data */
+	while ((cfg_data->prate * 1000) != ndata->new_rate) {
+		if (cfg_data->prate == 0)
+			return -EINVAL;
+		cfg_data++;
+	}
+
+	spin_lock(cpuclk->lock);
+
+	/*
+	 * For the selected PLL clock frequency, get the pre-defined divider
+	 * values. If the clock for sclk_hpm is not sourced from apll, then
+	 * the values for DIV_COPY and DIV_HPM dividers need not be set.
+	 */
+	div0 = cfg_data->div0;
+	if (test_bit(CLK_CPU_HAS_DIV1, &cpuclk->flags)) {
+		div1 = cfg_data->div1;
+		if (readl(base + E4210_SRC_CPU) & E4210_MUX_HPM_MASK)
+			div1 = readl(base + E4210_DIV_CPU1) &
+				(E4210_DIV1_HPM_MASK | E4210_DIV1_COPY_MASK);
+	}
+
+	/*
+	 * If the old parent clock speed is less than the clock speed of
+	 * the alternate parent, then it should be ensured that at no point
+	 * the armclk speed is more than the old_prate until the dividers are
+	 * set.  Also workaround the issue of the dividers being set to lower
+	 * values before the parent clock speed is set to new lower speed
+	 * (this can result in too high speed of armclk output clocks).
+	 */
+	if (alt_prate > ndata->old_rate || ndata->old_rate > ndata->new_rate) {
+		unsigned long tmp_rate = min(ndata->old_rate, ndata->new_rate);
+
+		alt_div = DIV_ROUND_UP(alt_prate, tmp_rate) - 1;
+		WARN_ON(alt_div >= MAX_DIV);
+
+		if (test_bit(CLK_CPU_NEEDS_DEBUG_ALT_DIV, &cpuclk->flags)) {
+			/*
+			 * In Exynos4210, ATB clock parent is also mout_core. So
+			 * ATB clock also needs to be mantained at safe speed.
+			 */
+			alt_div |= E4210_DIV0_ATB_MASK;
+			alt_div_mask |= E4210_DIV0_ATB_MASK;
+		}
+		exynos_set_safe_div(base, alt_div, alt_div_mask);
+		div0 |= alt_div;
+	}
+
+	/* select sclk_mpll as the alternate parent */
+	mux_reg = readl(base + E4210_SRC_CPU);
+	writel(mux_reg | (1 << 16), base + E4210_SRC_CPU);
+	wait_until_mux_stable(base + E4210_STAT_CPU, 16, 2);
+
+	/* alternate parent is active now. set the dividers */
+	writel(div0, base + E4210_DIV_CPU0);
+	wait_until_divider_stable(base + E4210_DIV_STAT_CPU0, DIV_MASK_ALL);
+
+	if (test_bit(CLK_CPU_HAS_DIV1, &cpuclk->flags)) {
+		writel(div1, base + E4210_DIV_CPU1);
+		wait_until_divider_stable(base + E4210_DIV_STAT_CPU1,
+				DIV_MASK_ALL);
+	}
+
+	spin_unlock(cpuclk->lock);
+	return 0;
+}
+
+/* handler for post-rate change notification from parent clock */
+static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
+			struct exynos_cpuclk *cpuclk, void __iomem *base)
+{
+	const struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg;
+	unsigned long div = 0, div_mask = DIV_MASK;
+	unsigned long mux_reg;
+
+	/* find out the divider values to use for clock data */
+	if (test_bit(CLK_CPU_NEEDS_DEBUG_ALT_DIV, &cpuclk->flags)) {
+		while ((cfg_data->prate * 1000) != ndata->new_rate) {
+			if (cfg_data->prate == 0)
+				return -EINVAL;
+			cfg_data++;
+		}
+	}
+
+	spin_lock(cpuclk->lock);
+
+	/* select mout_apll as the alternate parent */
+	mux_reg = readl(base + E4210_SRC_CPU);
+	writel(mux_reg & ~(1 << 16), base + E4210_SRC_CPU);
+	wait_until_mux_stable(base + E4210_STAT_CPU, 16, 1);
+
+	if (test_bit(CLK_CPU_NEEDS_DEBUG_ALT_DIV, &cpuclk->flags)) {
+		div |= (cfg_data->div0 & E4210_DIV0_ATB_MASK);
+		div_mask |= E4210_DIV0_ATB_MASK;
+	}
+
+	exynos_set_safe_div(base, div, div_mask);
+	spin_unlock(cpuclk->lock);
+	return 0;
+}
+
+/*
+ * This notifier function is called for the pre-rate and post-rate change
+ * notifications of the parent clock of cpuclk.
+ */
+static int exynos_cpuclk_notifier_cb(struct notifier_block *nb,
+				unsigned long event, void *data)
+{
+	struct clk_notifier_data *ndata = data;
+	struct exynos_cpuclk *cpuclk;
+	void __iomem *base;
+	int err = 0;
+
+	cpuclk = container_of(nb, struct exynos_cpuclk, clk_nb);
+	base = cpuclk->ctrl_base;
+
+	if (event == PRE_RATE_CHANGE)
+		err = exynos_cpuclk_pre_rate_change(ndata, cpuclk, base);
+	else if (event == POST_RATE_CHANGE)
+		err = exynos_cpuclk_post_rate_change(ndata, cpuclk, base);
+
+	return notifier_from_errno(err);
+}
+
+/* helper function to register a CPU clock */
+int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
+		unsigned int lookup_id, const char *name, const char *parent,
+		const char *alt_parent, unsigned long offset,
+		const struct exynos_cpuclk_cfg_data *cfg,
+		unsigned long num_cfgs, unsigned long flags)
+{
+	struct exynos_cpuclk *cpuclk;
+	struct clk_init_data init;
+	struct clk *clk;
+	int ret = 0;
+
+	cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
+	if (!cpuclk)
+		return -ENOMEM;
+
+	init.name = name;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = &parent;
+	init.num_parents = 1;
+	init.ops = &exynos_cpuclk_clk_ops;
+
+	cpuclk->hw.init = &init;
+	cpuclk->ctrl_base = ctx->reg_base + offset;
+	cpuclk->lock = &ctx->lock;
+	cpuclk->flags = flags;
+	cpuclk->clk_nb.notifier_call = exynos_cpuclk_notifier_cb;
+
+	cpuclk->alt_parent = __clk_lookup(alt_parent);
+	if (!cpuclk->alt_parent) {
+		pr_err("%s: could not lookup alternate parent %s\n",
+				__func__, alt_parent);
+		ret = -EINVAL;
+		goto free_cpuclk;
+	}
+
+	clk = __clk_lookup(parent);
+	if (!clk) {
+		pr_err("%s: could not lookup parent clock %s\n",
+				__func__, parent);
+		ret = -EINVAL;
+		goto free_cpuclk;
+	}
+
+	ret = clk_notifier_register(clk, &cpuclk->clk_nb);
+	if (ret) {
+		pr_err("%s: failed to register clock notifier for %s\n",
+				__func__, name);
+		goto free_cpuclk;
+	}
+
+	cpuclk->cfg = kmemdup(cfg, sizeof(*cfg) * num_cfgs, GFP_KERNEL);
+	if (!cpuclk->cfg) {
+		pr_err("%s: could not allocate memory for cpuclk data\n",
+				__func__);
+		ret = -ENOMEM;
+		goto unregister_clk_nb;
+	}
+
+	clk = clk_register(NULL, &cpuclk->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: could not register cpuclk %s\n", __func__,	name);
+		ret = PTR_ERR(clk);
+		goto free_cpuclk_data;
+	}
+
+	samsung_clk_add_lookup(ctx, clk, lookup_id);
+	return 0;
+
+free_cpuclk_data:
+	kfree(cpuclk->cfg);
+unregister_clk_nb:
+	clk_notifier_unregister(__clk_lookup(parent), &cpuclk->clk_nb);
+free_cpuclk:
+	kfree(cpuclk);
+	return ret;
+}
diff --git a/drivers/clk/samsung/clk-cpu.h b/drivers/clk/samsung/clk-cpu.h
new file mode 100644
index 000000000000..37874d3c3165
--- /dev/null
+++ b/drivers/clk/samsung/clk-cpu.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Common Clock Framework support for all PLL's in Samsung platforms
+*/
+
+#ifndef __SAMSUNG_CLK_CPU_H
+#define __SAMSUNG_CLK_CPU_H
+
+#include "clk.h"
+
+/**
+ * struct exynos_cpuclk_data: config data to setup cpu clocks.
+ * @prate: frequency of the primary parent clock (in KHz).
+ * @div0: value to be programmed in the div_cpu0 register.
+ * @div1: value to be programmed in the div_cpu1 register.
+ *
+ * This structure holds the divider configuration data for dividers in the CPU
+ * clock domain. The parent frequency at which these divider values are valid is
+ * specified in @prate. The @prate is the frequency of the primary parent clock.
+ * For CPU clock domains that do not have a DIV1 register, the @div1 member
+ * value is not used.
+ */
+struct exynos_cpuclk_cfg_data {
+	unsigned long	prate;
+	unsigned long	div0;
+	unsigned long	div1;
+};
+
+/**
+ * struct exynos_cpuclk: information about clock supplied to a CPU core.
+ * @hw:	handle between CCF and CPU clock.
+ * @alt_parent: alternate parent clock to use when switching the speed
+ *	of the primary parent clock.
+ * @ctrl_base:	base address of the clock controller.
+ * @lock: cpu clock domain register access lock.
+ * @cfg: cpu clock rate configuration data.
+ * @num_cfgs: number of array elements in @cfg array.
+ * @clk_nb: clock notifier registered for changes in clock speed of the
+ *	primary parent clock.
+ * @flags: configuration flags for the CPU clock.
+ *
+ * This structure holds information required for programming the CPU clock for
+ * various clock speeds.
+ */
+struct exynos_cpuclk {
+	struct clk_hw				hw;
+	struct clk				*alt_parent;
+	void __iomem				*ctrl_base;
+	spinlock_t				*lock;
+	const struct exynos_cpuclk_cfg_data	*cfg;
+	const unsigned long			num_cfgs;
+	struct notifier_block			clk_nb;
+	unsigned long				flags;
+
+/* The CPU clock registers has DIV1 configuration register */
+#define CLK_CPU_HAS_DIV1		(1 << 0)
+/* When ALT parent is active, debug clocks need safe divider values */
+#define CLK_CPU_NEEDS_DEBUG_ALT_DIV	(1 << 1)
+};
+
+extern int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx,
+			unsigned int lookup_id, const char *name,
+			const char *parent, const char *alt_parent,
+			unsigned long offset,
+			const struct exynos_cpuclk_cfg_data *cfg,
+			unsigned long num_cfgs, unsigned long flags);
+
+#endif /* __SAMSUNG_CLK_CPU_H */

From 6ae5a0b46fd82055ad5950539e1b36e4922c233f Mon Sep 17 00:00:00 2001
From: Thomas Abraham <thomas.ab@samsung.com>
Date: Fri, 3 Apr 2015 18:43:46 +0200
Subject: [PATCH 131/135] clk: samsung: exynos4: add cpu clock configuration
 data and instantiate cpu clock

With the addition of the new Samsung specific cpu-clock type, the
arm clock can be represented as a cpu-clock type. Add the CPU clock
configuration data and instantiate the CPU clock type for Exynos4210.

Changes by Bartlomiej:
- fixed issue with wrong dividers being setup by Common Clock Framework
  (by an addition of CLK_RECALC_NEW_RATES clock flag to mout_apll clock,
  without this change cpufreq-dt driver showed ~10 mA larger energy
  consumption when compared to cpufreq-exynos one when "performance"
  cpufreq governor was used on Exynos4210 SoC based Origen board), this
  was probably meant to be workarounded by use of CLK_GET_RATE_NOCACHE
  and CLK_DIVIDER_READ_ONLY clock flags in the original patchset (in
  "[PATCH v12 6/6] clk: samsung: remove unused clock aliases and update
  clock flags") but using these flags is not sufficient to fix the issue
  observed
- removed Exynos5250 and Exynos5420 support for now

Cc: Tomasz Figa <tomasz.figa@gmail.com>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 drivers/clk/samsung/clk-exynos4.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index 714d6ba782c8..cae2c048488d 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -19,6 +19,7 @@
 #include <linux/syscore_ops.h>
 
 #include "clk.h"
+#include "clk-cpu.h"
 
 /* Exynos4 clock controller register offsets */
 #define SRC_LEFTBUS		0x4200
@@ -534,7 +535,8 @@ static struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initda
 /* list of mux clocks supported in all exynos4 soc's */
 static struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
 	MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
-			CLK_SET_RATE_PARENT, 0, "mout_apll"),
+			CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0,
+			"mout_apll"),
 	MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1),
 	MUX(0, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1),
 	MUX(0, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1),
@@ -1378,6 +1380,22 @@ static void __init exynos4x12_core_down_clock(void)
 	__raw_writel(0x0, reg_base + E4X12_PWR_CTRL2);
 }
 
+#define E4210_CPU_DIV0(apll, pclk_dbg, atb, periph, corem1, corem0)	\
+		(((apll) << 24) | ((pclk_dbg) << 20) | ((atb) << 16) |	\
+		((periph) << 12) | ((corem1) << 8) | ((corem0) <<  4))
+#define E4210_CPU_DIV1(hpm, copy)					\
+		(((hpm) << 4) | ((copy) << 0))
+
+static const struct exynos_cpuclk_cfg_data e4210_armclk_d[] __initconst = {
+	{ 1200000, E4210_CPU_DIV0(7, 1, 4, 3, 7, 3), E4210_CPU_DIV1(0, 5), },
+	{ 1000000, E4210_CPU_DIV0(7, 1, 4, 3, 7, 3), E4210_CPU_DIV1(0, 4), },
+	{  800000, E4210_CPU_DIV0(7, 1, 3, 3, 7, 3), E4210_CPU_DIV1(0, 3), },
+	{  500000, E4210_CPU_DIV0(7, 1, 3, 3, 7, 3), E4210_CPU_DIV1(0, 3), },
+	{  400000, E4210_CPU_DIV0(7, 1, 3, 3, 7, 3), E4210_CPU_DIV1(0, 3), },
+	{  200000, E4210_CPU_DIV0(0, 1, 1, 1, 3, 1), E4210_CPU_DIV1(0, 3), },
+	{  0 },
+};
+
 /* register exynos4 clocks */
 static void __init exynos4_clk_init(struct device_node *np,
 				    enum exynos4_soc soc)
@@ -1455,6 +1473,10 @@ static void __init exynos4_clk_init(struct device_node *np,
 		samsung_clk_register_fixed_factor(ctx,
 			exynos4210_fixed_factor_clks,
 			ARRAY_SIZE(exynos4210_fixed_factor_clks));
+		exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
+			mout_core_p4210[0], mout_core_p4210[1], 0x14200,
+			e4210_armclk_d, ARRAY_SIZE(e4210_armclk_d),
+			CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1);
 	} else {
 		samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
 			ARRAY_SIZE(exynos4x12_mux_clks));

From 131323cd16e563499caedc93a9c2f82fce4c966c Mon Sep 17 00:00:00 2001
From: Thomas Abraham <thomas.ab@samsung.com>
Date: Fri, 3 Apr 2015 18:43:48 +0200
Subject: [PATCH 132/135] ARM: Exynos: switch to using generic cpufreq driver
 for Exynos4210

The new CPU clock type allows the use of generic CPUfreq driver.
Switch Exynos4210 to using generic cpufreq driver.

Changes by Bartlomiej:
- removed non-Exynos4210 support for now

Cc: Tomasz Figa <tomasz.figa@gmail.com>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 arch/arm/mach-exynos/exynos.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 5917a30eee33..9cb17ff1e152 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -224,6 +224,25 @@ static void __init exynos_init_irq(void)
 	exynos_map_pmu();
 }
 
+static const struct of_device_id exynos_cpufreq_matches[] = {
+	{ .compatible = "samsung,exynos4210", .data = "cpufreq-dt" },
+	{ /* sentinel */ }
+};
+
+static void __init exynos_cpufreq_init(void)
+{
+	struct device_node *root = of_find_node_by_path("/");
+	const struct of_device_id *match;
+
+	match = of_match_node(exynos_cpufreq_matches, root);
+	if (!match) {
+		platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
+		return;
+	}
+
+	platform_device_register_simple(match->data, -1, NULL, 0);
+}
+
 static void __init exynos_dt_machine_init(void)
 {
 	/*
@@ -245,7 +264,7 @@ static void __init exynos_dt_machine_init(void)
 	    of_machine_is_compatible("samsung,exynos5250"))
 		platform_device_register(&exynos_cpuidle);
 
-	platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
+	exynos_cpufreq_init();
 
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }

From 8eb92ab68f961bb9045d8d7882cceb2d6be0659d Mon Sep 17 00:00:00 2001
From: Thomas Abraham <thomas.ab@samsung.com>
Date: Fri, 3 Apr 2015 18:43:49 +0200
Subject: [PATCH 133/135] cpufreq: exynos: remove Exynos4210 specific cpufreq
 driver support

Exynos4210 based platforms have switched over to use generic
cpufreq driver for cpufreq functionality. So the Exynos
specific cpufreq support for these platforms can be removed.

Changes by Bartlomiej:
- dropped Exynos5250 support removal for now
- updated exynos-cpufreq.[c,h]

Cc: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Thomas Abraham <thomas.ab@samsung.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 drivers/cpufreq/Kconfig.arm          |  11 --
 drivers/cpufreq/Makefile             |   1 -
 drivers/cpufreq/exynos-cpufreq.c     |   5 +-
 drivers/cpufreq/exynos-cpufreq.h     |   9 --
 drivers/cpufreq/exynos4210-cpufreq.c | 184 ---------------------------
 5 files changed, 1 insertion(+), 209 deletions(-)
 delete mode 100644 drivers/cpufreq/exynos4210-cpufreq.c

diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 4f3dbc8cf729..a86a196e32f6 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -36,17 +36,6 @@ config ARM_EXYNOS_CPUFREQ
 
 	  If in doubt, say N.
 
-config ARM_EXYNOS4210_CPUFREQ
-	bool "SAMSUNG EXYNOS4210"
-	depends on CPU_EXYNOS4210
-	depends on ARM_EXYNOS_CPUFREQ
-	default y
-	help
-	  This adds the CPUFreq driver for Samsung EXYNOS4210
-	  SoC (S5PV310 or S5PC210).
-
-	  If in doubt, say N.
-
 config ARM_EXYNOS4X12_CPUFREQ
 	bool "SAMSUNG EXYNOS4x12"
 	depends on SOC_EXYNOS4212 || SOC_EXYNOS4412
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index cdce92ae2e8b..2169bf792db7 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -54,7 +54,6 @@ obj-$(CONFIG_ARCH_DAVINCI)		+= davinci-cpufreq.o
 obj-$(CONFIG_UX500_SOC_DB8500)		+= dbx500-cpufreq.o
 obj-$(CONFIG_ARM_EXYNOS_CPUFREQ)	+= arm-exynos-cpufreq.o
 arm-exynos-cpufreq-y					:= exynos-cpufreq.o
-arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS4210_CPUFREQ)	+= exynos4210-cpufreq.o
 arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ)	+= exynos4x12-cpufreq.o
 arm-exynos-cpufreq-$(CONFIG_ARM_EXYNOS5250_CPUFREQ)	+= exynos5250-cpufreq.o
 obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ)	+= exynos5440-cpufreq.o
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 82d2fbb20f7e..fb24aaf4adcf 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -168,10 +168,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
 
 	exynos_info->dev = &pdev->dev;
 
-	if (of_machine_is_compatible("samsung,exynos4210")) {
-		exynos_info->type = EXYNOS_SOC_4210;
-		ret = exynos4210_cpufreq_init(exynos_info);
-	} else if (of_machine_is_compatible("samsung,exynos4212")) {
+	if (of_machine_is_compatible("samsung,exynos4212")) {
 		exynos_info->type = EXYNOS_SOC_4212;
 		ret = exynos4x12_cpufreq_init(exynos_info);
 	} else if (of_machine_is_compatible("samsung,exynos4412")) {
diff --git a/drivers/cpufreq/exynos-cpufreq.h b/drivers/cpufreq/exynos-cpufreq.h
index 9f2062a7cc02..a3855e4d913d 100644
--- a/drivers/cpufreq/exynos-cpufreq.h
+++ b/drivers/cpufreq/exynos-cpufreq.h
@@ -18,7 +18,6 @@ enum cpufreq_level_index {
 };
 
 enum exynos_soc_type {
-	EXYNOS_SOC_4210,
 	EXYNOS_SOC_4212,
 	EXYNOS_SOC_4412,
 	EXYNOS_SOC_5250,
@@ -53,14 +52,6 @@ struct exynos_dvfs_info {
 	void __iomem	*cmu_regs;
 };
 
-#ifdef CONFIG_ARM_EXYNOS4210_CPUFREQ
-extern int exynos4210_cpufreq_init(struct exynos_dvfs_info *);
-#else
-static inline int exynos4210_cpufreq_init(struct exynos_dvfs_info *info)
-{
-	return -EOPNOTSUPP;
-}
-#endif
 #ifdef CONFIG_ARM_EXYNOS4X12_CPUFREQ
 extern int exynos4x12_cpufreq_init(struct exynos_dvfs_info *);
 #else
diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
deleted file mode 100644
index 843ec824fd91..000000000000
--- a/drivers/cpufreq/exynos4210-cpufreq.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4210 - CPU frequency scaling 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/module.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/cpufreq.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-
-#include "exynos-cpufreq.h"
-
-static struct clk *cpu_clk;
-static struct clk *moutcore;
-static struct clk *mout_mpll;
-static struct clk *mout_apll;
-static struct exynos_dvfs_info *cpufreq;
-
-static unsigned int exynos4210_volt_table[] = {
-	1250000, 1150000, 1050000, 975000, 950000,
-};
-
-static struct cpufreq_frequency_table exynos4210_freq_table[] = {
-	{0, L0, 1200 * 1000},
-	{0, L1, 1000 * 1000},
-	{0, L2,  800 * 1000},
-	{0, L3,  500 * 1000},
-	{0, L4,  200 * 1000},
-	{0, 0, CPUFREQ_TABLE_END},
-};
-
-static struct apll_freq apll_freq_4210[] = {
-	/*
-	 * values:
-	 * freq
-	 * clock divider for CORE, COREM0, COREM1, PERIPH, ATB, PCLK_DBG, APLL, RESERVED
-	 * clock divider for COPY, HPM, RESERVED
-	 * PLL M, P, S
-	 */
-	APLL_FREQ(1200, 0, 3, 7, 3, 4, 1, 7, 0, 5, 0, 0, 150, 3, 1),
-	APLL_FREQ(1000, 0, 3, 7, 3, 4, 1, 7, 0, 4, 0, 0, 250, 6, 1),
-	APLL_FREQ(800,  0, 3, 7, 3, 3, 1, 7, 0, 3, 0, 0, 200, 6, 1),
-	APLL_FREQ(500,  0, 3, 7, 3, 3, 1, 7, 0, 3, 0, 0, 250, 6, 2),
-	APLL_FREQ(200,  0, 1, 3, 1, 3, 1, 0, 0, 3, 0, 0, 200, 6, 3),
-};
-
-static void exynos4210_set_clkdiv(unsigned int div_index)
-{
-	unsigned int tmp;
-
-	/* Change Divider - CPU0 */
-
-	tmp = apll_freq_4210[div_index].clk_div_cpu0;
-
-	__raw_writel(tmp, cpufreq->cmu_regs + EXYNOS4_CLKDIV_CPU);
-
-	do {
-		tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKDIV_STATCPU);
-	} while (tmp & 0x1111111);
-
-	/* Change Divider - CPU1 */
-
-	tmp = apll_freq_4210[div_index].clk_div_cpu1;
-
-	__raw_writel(tmp, cpufreq->cmu_regs + EXYNOS4_CLKDIV_CPU1);
-
-	do {
-		tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKDIV_STATCPU1);
-	} while (tmp & 0x11);
-}
-
-static void exynos4210_set_apll(unsigned int index)
-{
-	unsigned int tmp, freq = apll_freq_4210[index].freq;
-
-	/* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
-	clk_set_parent(moutcore, mout_mpll);
-
-	do {
-		tmp = (__raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKMUX_STATCPU)
-			>> EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT);
-		tmp &= 0x7;
-	} while (tmp != 0x2);
-
-	clk_set_rate(mout_apll, freq * 1000);
-
-	/* MUX_CORE_SEL = APLL */
-	clk_set_parent(moutcore, mout_apll);
-
-	do {
-		tmp = __raw_readl(cpufreq->cmu_regs + EXYNOS4_CLKMUX_STATCPU);
-		tmp &= EXYNOS4_CLKMUX_STATCPU_MUXCORE_MASK;
-	} while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT));
-}
-
-static void exynos4210_set_frequency(unsigned int old_index,
-				     unsigned int new_index)
-{
-	if (old_index > new_index) {
-		exynos4210_set_clkdiv(new_index);
-		exynos4210_set_apll(new_index);
-	} else if (old_index < new_index) {
-		exynos4210_set_apll(new_index);
-		exynos4210_set_clkdiv(new_index);
-	}
-}
-
-int exynos4210_cpufreq_init(struct exynos_dvfs_info *info)
-{
-	struct device_node *np;
-	unsigned long rate;
-
-	/*
-	 * HACK: This is a temporary workaround to get access to clock
-	 * controller registers directly and remove static mappings and
-	 * dependencies on platform headers. It is necessary to enable
-	 * Exynos multi-platform support and will be removed together with
-	 * this whole driver as soon as Exynos gets migrated to use
-	 * cpufreq-dt driver.
-	 */
-	np = of_find_compatible_node(NULL, NULL, "samsung,exynos4210-clock");
-	if (!np) {
-		pr_err("%s: failed to find clock controller DT node\n",
-			__func__);
-		return -ENODEV;
-	}
-
-	info->cmu_regs = of_iomap(np, 0);
-	if (!info->cmu_regs) {
-		pr_err("%s: failed to map CMU registers\n", __func__);
-		return -EFAULT;
-	}
-
-	cpu_clk = clk_get(NULL, "armclk");
-	if (IS_ERR(cpu_clk))
-		return PTR_ERR(cpu_clk);
-
-	moutcore = clk_get(NULL, "moutcore");
-	if (IS_ERR(moutcore))
-		goto err_moutcore;
-
-	mout_mpll = clk_get(NULL, "mout_mpll");
-	if (IS_ERR(mout_mpll))
-		goto err_mout_mpll;
-
-	rate = clk_get_rate(mout_mpll) / 1000;
-
-	mout_apll = clk_get(NULL, "mout_apll");
-	if (IS_ERR(mout_apll))
-		goto err_mout_apll;
-
-	info->mpll_freq_khz = rate;
-	/* 800Mhz */
-	info->pll_safe_idx = L2;
-	info->cpu_clk = cpu_clk;
-	info->volt_table = exynos4210_volt_table;
-	info->freq_table = exynos4210_freq_table;
-	info->set_freq = exynos4210_set_frequency;
-
-	cpufreq = info;
-
-	return 0;
-
-err_mout_apll:
-	clk_put(mout_mpll);
-err_mout_mpll:
-	clk_put(moutcore);
-err_moutcore:
-	clk_put(cpu_clk);
-
-	pr_debug("%s: failed initialization\n", __func__);
-	return -EINVAL;
-}

From 41655239eaed741ac8da066bc43c2483c78e61ec Mon Sep 17 00:00:00 2001
From: Daniel Thompson <daniel.thompson@linaro.org>
Date: Wed, 10 Jun 2015 21:09:36 +0100
Subject: [PATCH 134/135] dt-bindings: Document the STM32F4 clock bindings

This adds documentation of device tree bindings for the clock related
portions of the STM32 RCC block.

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
Acked-by: Maxime Coquelin <maxime.coquelin@st.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 .../bindings/clock/st,stm32-rcc.txt           | 65 +++++++++++++++++++
 1 file changed, 65 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/st,stm32-rcc.txt

diff --git a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
new file mode 100644
index 000000000000..fee3205cdff9
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
@@ -0,0 +1,65 @@
+STMicroelectronics STM32 Reset and Clock Controller
+===================================================
+
+The RCC IP is both a reset and a clock controller. This documentation only
+describes the clock part.
+
+Please also refer to clock-bindings.txt in this directory for common clock
+controller binding usage.
+
+Required properties:
+- compatible: Should be "st,stm32f42xx-rcc"
+- reg: should be register base and length as documented in the
+  datasheet
+- #clock-cells: 2, device nodes should specify the clock in their "clocks"
+  property, containing a phandle to the clock device node, an index selecting
+  between gated clocks and other clocks and an index specifying the clock to
+  use.
+
+Example:
+
+	rcc: rcc@40023800 {
+		#clock-cells = <2>
+		compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
+		reg = <0x40023800 0x400>;
+	};
+
+Specifying gated clocks
+=======================
+
+The primary index must be set to 0.
+
+The secondary index is the bit number within the RCC register bank, starting
+from the first RCC clock enable register (RCC_AHB1ENR, address offset 0x30).
+
+It is calculated as: index = register_offset / 4 * 32 + bit_offset.
+Where bit_offset is the bit offset within the register (LSB is 0, MSB is 31).
+
+Example:
+
+	/* Gated clock, AHB1 bit 0 (GPIOA) */
+	... {
+		clocks = <&rcc 0 0>
+	};
+
+	/* Gated clock, AHB2 bit 4 (CRYP) */
+	... {
+		clocks = <&rcc 0 36>
+	};
+
+Specifying other clocks
+=======================
+
+The primary index must be set to 1.
+
+The secondary index is bound with the following magic numbers:
+
+	0	SYSTICK
+	1	FCLK
+
+Example:
+
+	/* Misc clock, FCLK */
+	... {
+		clocks = <&rcc 1 1>
+	};

From 358bdf892f6bfacf20884b54a35ab038321f06f9 Mon Sep 17 00:00:00 2001
From: Daniel Thompson <daniel.thompson@linaro.org>
Date: Wed, 10 Jun 2015 21:09:37 +0100
Subject: [PATCH 135/135] clk: stm32: Add clock driver for STM32F4[23]xxx
 devices

The driver supports decoding and statically modelling PLL state (i.e.
we inherit state from bootloader) and provides support for all
peripherals that support simple one-bit gated clocks. The covers all
peripherals whose clocks come from the AHB, APB1 or APB2 buses.

It has been tested on an STM32F429I-Discovery board. The clock counts
for TIM2, USART1 and SYSTICK are all set correctly and the wall clock
looks OK when checked with a stopwatch. I have also tested a prototype
driver for the RNG hardware. The RNG clock is correctly enabled by the
framework (also did inverse test and proved that by changing DT to
configure the wrong clock bit then we observe the RNG driver to fail).

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
Reviewed-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
[sboyd@codeaurora.org: Silence sparse warnings]
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/Makefile      |   1 +
 drivers/clk/clk-stm32f4.c | 380 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 381 insertions(+)
 create mode 100644 drivers/clk/clk-stm32f4.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 256977ed050a..fc789a07cb5f 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_COMMON_CLK_S2MPS11)	+= clk-s2mps11.o
 obj-$(CONFIG_COMMON_CLK_SI5351)		+= clk-si5351.o
 obj-$(CONFIG_COMMON_CLK_SI570)		+= clk-si570.o
 obj-$(CONFIG_COMMON_CLK_CDCE925)	+= clk-cdce925.o
+obj-$(CONFIG_ARCH_STM32)		+= clk-stm32f4.o
 obj-$(CONFIG_CLK_TWL6040)		+= clk-twl6040.o
 obj-$(CONFIG_ARCH_U300)			+= clk-u300.o
 obj-$(CONFIG_ARCH_VT8500)		+= clk-vt8500.o
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
new file mode 100644
index 000000000000..b9b12a742970
--- /dev/null
+++ b/drivers/clk/clk-stm32f4.c
@@ -0,0 +1,380 @@
+/*
+ * Author: Daniel Thompson <daniel.thompson@linaro.org>
+ *
+ * Inspired by clk-asm9260.c .
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#define STM32F4_RCC_PLLCFGR		0x04
+#define STM32F4_RCC_CFGR		0x08
+#define STM32F4_RCC_AHB1ENR		0x30
+#define STM32F4_RCC_AHB2ENR		0x34
+#define STM32F4_RCC_AHB3ENR		0x38
+#define STM32F4_RCC_APB1ENR		0x40
+#define STM32F4_RCC_APB2ENR		0x44
+
+struct stm32f4_gate_data {
+	u8	offset;
+	u8	bit_idx;
+	const char *name;
+	const char *parent_name;
+	unsigned long flags;
+};
+
+static const struct stm32f4_gate_data stm32f4_gates[] __initconst = {
+	{ STM32F4_RCC_AHB1ENR,  0,	"gpioa",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  1,	"gpiob",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  2,	"gpioc",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  3,	"gpiod",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  4,	"gpioe",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  5,	"gpiof",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  6,	"gpiog",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  7,	"gpioh",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  8,	"gpioi",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  9,	"gpioj",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 10,	"gpiok",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 12,	"crc",		"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 18,	"bkpsra",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 20,	"ccmdatam",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 21,	"dma1",		"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 22,	"dma2",		"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 23,	"dma2d",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 25,	"ethmac",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 26,	"ethmactx",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 27,	"ethmacrx",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 28,	"ethmacptp",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 29,	"otghs",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 30,	"otghsulpi",	"ahb_div" },
+
+	{ STM32F4_RCC_AHB2ENR,  0,	"dcmi",		"ahb_div" },
+	{ STM32F4_RCC_AHB2ENR,  4,	"cryp",		"ahb_div" },
+	{ STM32F4_RCC_AHB2ENR,  5,	"hash",		"ahb_div" },
+	{ STM32F4_RCC_AHB2ENR,  6,	"rng",		"pll48" },
+	{ STM32F4_RCC_AHB2ENR,  7,	"otgfs",	"pll48" },
+
+	{ STM32F4_RCC_AHB3ENR,  0,	"fmc",		"ahb_div",
+		CLK_IGNORE_UNUSED },
+
+	{ STM32F4_RCC_APB1ENR,  0,	"tim2",		"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  1,	"tim3",		"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  2,	"tim4",		"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  3,	"tim5",		"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  4,	"tim6",		"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  5,	"tim7",		"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  6,	"tim12",	"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  7,	"tim13",	"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  8,	"tim14",	"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR, 11,	"wwdg",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 14,	"spi2",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 15,	"spi3",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 17,	"uart2",	"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 18,	"uart3",	"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 19,	"uart4",	"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 20,	"uart5",	"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 21,	"i2c1",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 22,	"i2c2",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 23,	"i2c3",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 25,	"can1",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 26,	"can2",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 28,	"pwr",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 29,	"dac",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 30,	"uart7",	"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 31,	"uart8",	"apb1_div" },
+
+	{ STM32F4_RCC_APB2ENR,  0,	"tim1",		"apb2_mul" },
+	{ STM32F4_RCC_APB2ENR,  1,	"tim8",		"apb2_mul" },
+	{ STM32F4_RCC_APB2ENR,  4,	"usart1",	"apb2_div" },
+	{ STM32F4_RCC_APB2ENR,  5,	"usart6",	"apb2_div" },
+	{ STM32F4_RCC_APB2ENR,  8,	"adc1",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR,  9,	"adc2",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 10,	"adc3",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 11,	"sdio",		"pll48" },
+	{ STM32F4_RCC_APB2ENR, 12,	"spi1",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 13,	"spi4",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 14,	"syscfg",	"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 16,	"tim9",		"apb2_mul" },
+	{ STM32F4_RCC_APB2ENR, 17,	"tim10",	"apb2_mul" },
+	{ STM32F4_RCC_APB2ENR, 18,	"tim11",	"apb2_mul" },
+	{ STM32F4_RCC_APB2ENR, 20,	"spi5",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 21,	"spi6",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 22,	"sai1",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 26,	"ltdc",		"apb2_div" },
+};
+
+/*
+ * MAX_CLKS is the maximum value in the enumeration below plus the combined
+ * hweight of stm32f42xx_gate_map (plus one).
+ */
+#define MAX_CLKS 74
+
+enum { SYSTICK, FCLK };
+
+/*
+ * This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx
+ * have gate bits associated with them. Its combined hweight is 71.
+ */
+static const u64 stm32f42xx_gate_map[] = { 0x000000f17ef417ffull,
+					   0x0000000000000001ull,
+					   0x04777f33f6fec9ffull };
+
+static struct clk *clks[MAX_CLKS];
+static DEFINE_SPINLOCK(stm32f4_clk_lock);
+static void __iomem *base;
+
+/*
+ * "Multiplier" device for APBx clocks.
+ *
+ * The APBx dividers are power-of-two dividers and, if *not* running in 1:1
+ * mode, they also tap out the one of the low order state bits to run the
+ * timers. ST datasheets represent this feature as a (conditional) clock
+ * multiplier.
+ */
+struct clk_apb_mul {
+	struct clk_hw hw;
+	u8 bit_idx;
+};
+
+#define to_clk_apb_mul(_hw) container_of(_hw, struct clk_apb_mul, hw)
+
+static unsigned long clk_apb_mul_recalc_rate(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	struct clk_apb_mul *am = to_clk_apb_mul(hw);
+
+	if (readl(base + STM32F4_RCC_CFGR) & BIT(am->bit_idx))
+		return parent_rate * 2;
+
+	return parent_rate;
+}
+
+static long clk_apb_mul_round_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long *prate)
+{
+	struct clk_apb_mul *am = to_clk_apb_mul(hw);
+	unsigned long mult = 1;
+
+	if (readl(base + STM32F4_RCC_CFGR) & BIT(am->bit_idx))
+		mult = 2;
+
+	if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
+		unsigned long best_parent = rate / mult;
+
+		*prate =
+		    __clk_round_rate(__clk_get_parent(hw->clk), best_parent);
+	}
+
+	return *prate * mult;
+}
+
+static int clk_apb_mul_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	/*
+	 * We must report success but we can do so unconditionally because
+	 * clk_apb_mul_round_rate returns values that ensure this call is a
+	 * nop.
+	 */
+
+	return 0;
+}
+
+static const struct clk_ops clk_apb_mul_factor_ops = {
+	.round_rate = clk_apb_mul_round_rate,
+	.set_rate = clk_apb_mul_set_rate,
+	.recalc_rate = clk_apb_mul_recalc_rate,
+};
+
+static struct clk *clk_register_apb_mul(struct device *dev, const char *name,
+					const char *parent_name,
+					unsigned long flags, u8 bit_idx)
+{
+	struct clk_apb_mul *am;
+	struct clk_init_data init;
+	struct clk *clk;
+
+	am = kzalloc(sizeof(*am), GFP_KERNEL);
+	if (!am)
+		return ERR_PTR(-ENOMEM);
+
+	am->bit_idx = bit_idx;
+	am->hw.init = &init;
+
+	init.name = name;
+	init.ops = &clk_apb_mul_factor_ops;
+	init.flags = flags;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	clk = clk_register(dev, &am->hw);
+
+	if (IS_ERR(clk))
+		kfree(am);
+
+	return clk;
+}
+
+/*
+ * Decode current PLL state and (statically) model the state we inherit from
+ * the bootloader.
+ */
+static void stm32f4_rcc_register_pll(const char *hse_clk, const char *hsi_clk)
+{
+	unsigned long pllcfgr = readl(base + STM32F4_RCC_PLLCFGR);
+
+	unsigned long pllm   = pllcfgr & 0x3f;
+	unsigned long plln   = (pllcfgr >> 6) & 0x1ff;
+	unsigned long pllp   = BIT(((pllcfgr >> 16) & 3) + 1);
+	const char   *pllsrc = pllcfgr & BIT(22) ? hse_clk : hsi_clk;
+	unsigned long pllq   = (pllcfgr >> 24) & 0xf;
+
+	clk_register_fixed_factor(NULL, "vco", pllsrc, 0, plln, pllm);
+	clk_register_fixed_factor(NULL, "pll", "vco", 0, 1, pllp);
+	clk_register_fixed_factor(NULL, "pll48", "vco", 0, 1, pllq);
+}
+
+/*
+ * Converts the primary and secondary indices (as they appear in DT) to an
+ * offset into our struct clock array.
+ */
+static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
+{
+	u64 table[ARRAY_SIZE(stm32f42xx_gate_map)];
+
+	if (primary == 1) {
+		if (WARN_ON(secondary > FCLK))
+			return -EINVAL;
+		return secondary;
+	}
+
+	memcpy(table, stm32f42xx_gate_map, sizeof(table));
+
+	/* only bits set in table can be used as indices */
+	if (WARN_ON(secondary > 8 * sizeof(table) ||
+		    0 == (table[BIT_ULL_WORD(secondary)] &
+			  BIT_ULL_MASK(secondary))))
+		return -EINVAL;
+
+	/* mask out bits above our current index */
+	table[BIT_ULL_WORD(secondary)] &=
+	    GENMASK_ULL(secondary % BITS_PER_LONG_LONG, 0);
+
+	return FCLK + hweight64(table[0]) +
+	       (BIT_ULL_WORD(secondary) >= 1 ? hweight64(table[1]) : 0) +
+	       (BIT_ULL_WORD(secondary) >= 2 ? hweight64(table[2]) : 0);
+}
+
+static struct clk *
+stm32f4_rcc_lookup_clk(struct of_phandle_args *clkspec, void *data)
+{
+	int i = stm32f4_rcc_lookup_clk_idx(clkspec->args[0], clkspec->args[1]);
+
+	if (i < 0)
+		return ERR_PTR(-EINVAL);
+
+	return clks[i];
+}
+
+static const char *sys_parents[] __initdata =   { "hsi", NULL, "pll" };
+
+static const struct clk_div_table ahb_div_table[] = {
+	{ 0x0,   1 }, { 0x1,   1 }, { 0x2,   1 }, { 0x3,   1 },
+	{ 0x4,   1 }, { 0x5,   1 }, { 0x6,   1 }, { 0x7,   1 },
+	{ 0x8,   2 }, { 0x9,   4 }, { 0xa,   8 }, { 0xb,  16 },
+	{ 0xc,  64 }, { 0xd, 128 }, { 0xe, 256 }, { 0xf, 512 },
+	{ 0 },
+};
+
+static const struct clk_div_table apb_div_table[] = {
+	{ 0,  1 }, { 0,  1 }, { 0,  1 }, { 0,  1 },
+	{ 4,  2 }, { 5,  4 }, { 6,  8 }, { 7, 16 },
+	{ 0 },
+};
+
+static void __init stm32f4_rcc_init(struct device_node *np)
+{
+	const char *hse_clk;
+	int n;
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		pr_err("%s: unable to map resource", np->name);
+		return;
+	}
+
+	hse_clk = of_clk_get_parent_name(np, 0);
+
+	clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0,
+			16000000, 160000);
+	stm32f4_rcc_register_pll(hse_clk, "hsi");
+
+	sys_parents[1] = hse_clk;
+	clk_register_mux_table(
+	    NULL, "sys", sys_parents, ARRAY_SIZE(sys_parents), 0,
+	    base + STM32F4_RCC_CFGR, 0, 3, 0, NULL, &stm32f4_clk_lock);
+
+	clk_register_divider_table(NULL, "ahb_div", "sys",
+				   CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
+				   4, 4, 0, ahb_div_table, &stm32f4_clk_lock);
+
+	clk_register_divider_table(NULL, "apb1_div", "ahb_div",
+				   CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
+				   10, 3, 0, apb_div_table, &stm32f4_clk_lock);
+	clk_register_apb_mul(NULL, "apb1_mul", "apb1_div",
+			     CLK_SET_RATE_PARENT, 12);
+
+	clk_register_divider_table(NULL, "apb2_div", "ahb_div",
+				   CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
+				   13, 3, 0, apb_div_table, &stm32f4_clk_lock);
+	clk_register_apb_mul(NULL, "apb2_mul", "apb2_div",
+			     CLK_SET_RATE_PARENT, 15);
+
+	clks[SYSTICK] = clk_register_fixed_factor(NULL, "systick", "ahb_div",
+						  0, 1, 8);
+	clks[FCLK] = clk_register_fixed_factor(NULL, "fclk", "ahb_div",
+					       0, 1, 1);
+
+	for (n = 0; n < ARRAY_SIZE(stm32f4_gates); n++) {
+		const struct stm32f4_gate_data *gd = &stm32f4_gates[n];
+		unsigned int secondary =
+		    8 * (gd->offset - STM32F4_RCC_AHB1ENR) + gd->bit_idx;
+		int idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
+
+		if (idx < 0)
+			goto fail;
+
+		clks[idx] = clk_register_gate(
+		    NULL, gd->name, gd->parent_name, gd->flags,
+		    base + gd->offset, gd->bit_idx, 0, &stm32f4_clk_lock);
+
+		if (IS_ERR(clks[n])) {
+			pr_err("%s: Unable to register leaf clock %s\n",
+			       np->full_name, gd->name);
+			goto fail;
+		}
+	}
+
+	of_clk_add_provider(np, stm32f4_rcc_lookup_clk, NULL);
+	return;
+fail:
+	iounmap(base);
+}
+CLK_OF_DECLARE(stm32f4_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);