diff options
Diffstat (limited to 'drivers/clk/clk.c')
| -rw-r--r-- | drivers/clk/clk.c | 677 | 
1 files changed, 530 insertions, 147 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index a004769528e..8b73edef151 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -21,6 +21,8 @@  #include <linux/init.h>  #include <linux/sched.h> +#include "clk.h" +  static DEFINE_SPINLOCK(enable_lock);  static DEFINE_MUTEX(prepare_lock); @@ -92,7 +94,7 @@ static void clk_enable_unlock(unsigned long flags)  /***        debugfs support        ***/ -#ifdef CONFIG_COMMON_CLK_DEBUG +#ifdef CONFIG_DEBUG_FS  #include <linux/debugfs.h>  static struct dentry *rootdir; @@ -104,11 +106,11 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)  	if (!c)  		return; -	seq_printf(s, "%*s%-*s %-11d %-12d %-10lu", +	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu\n",  		   level * 3 + 1, "",  		   30 - level * 3, c->name, -		   c->enable_count, c->prepare_count, clk_get_rate(c)); -	seq_printf(s, "\n"); +		   c->enable_count, c->prepare_count, clk_get_rate(c), +		   clk_get_accuracy(c));  }  static void clk_summary_show_subtree(struct seq_file *s, struct clk *c, @@ -129,8 +131,8 @@ static int clk_summary_show(struct seq_file *s, void *data)  {  	struct clk *c; -	seq_printf(s, "   clock                        enable_cnt  prepare_cnt  rate\n"); -	seq_printf(s, "---------------------------------------------------------------------\n"); +	seq_puts(s, "   clock                         enable_cnt  prepare_cnt        rate   accuracy\n"); +	seq_puts(s, "--------------------------------------------------------------------------------\n");  	clk_prepare_lock(); @@ -167,6 +169,7 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level)  	seq_printf(s, "\"enable_count\": %d,", c->enable_count);  	seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);  	seq_printf(s, "\"rate\": %lu", clk_get_rate(c)); +	seq_printf(s, "\"accuracy\": %lu", clk_get_accuracy(c));  }  static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level) @@ -248,6 +251,11 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)  	if (!d)  		goto err_out; +	d = debugfs_create_u32("clk_accuracy", S_IRUGO, clk->dentry, +			(u32 *)&clk->accuracy); +	if (!d) +		goto err_out; +  	d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,  			(u32 *)&clk->flags);  	if (!d) @@ -268,11 +276,16 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)  	if (!d)  		goto err_out; +	if (clk->ops->debug_init) +		if (clk->ops->debug_init(clk->hw, clk->dentry)) +			goto err_out; +  	ret = 0;  	goto out;  err_out: -	debugfs_remove(clk->dentry); +	debugfs_remove_recursive(clk->dentry); +	clk->dentry = NULL;  out:  	return ret;  } @@ -342,6 +355,21 @@ out:  	return ret;  } + /** + * clk_debug_unregister - remove a clk node from the debugfs clk tree + * @clk: 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. + * + * Caller must hold prepare_lock. + */ +static void clk_debug_unregister(struct clk *clk) +{ +	debugfs_remove_recursive(clk->dentry); +} +  /**   * clk_debug_reparent - reparent clk node in the debugfs clk tree   * @clk: the clk being reparented @@ -432,6 +460,9 @@ static inline int clk_debug_register(struct clk *clk) { return 0; }  static inline void clk_debug_reparent(struct clk *clk, struct clk *new_parent)  {  } +static inline void clk_debug_unregister(struct clk *clk) +{ +}  #endif  /* caller must hold prepare_lock */ @@ -547,16 +578,19 @@ struct clk_hw *__clk_get_hw(struct clk *clk)  {  	return !clk ? NULL : clk->hw;  } +EXPORT_SYMBOL_GPL(__clk_get_hw);  u8 __clk_get_num_parents(struct clk *clk)  {  	return !clk ? 0 : clk->num_parents;  } +EXPORT_SYMBOL_GPL(__clk_get_num_parents);  struct clk *__clk_get_parent(struct clk *clk)  {  	return !clk ? NULL : clk->parent;  } +EXPORT_SYMBOL_GPL(__clk_get_parent);  struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)  { @@ -570,6 +604,7 @@ struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)  	else  		return clk->parents[index];  } +EXPORT_SYMBOL_GPL(clk_get_parent_by_index);  unsigned int __clk_get_enable_count(struct clk *clk)  { @@ -601,6 +636,15 @@ unsigned long __clk_get_rate(struct clk *clk)  out:  	return ret;  } +EXPORT_SYMBOL_GPL(__clk_get_rate); + +unsigned long __clk_get_accuracy(struct clk *clk) +{ +	if (!clk) +		return 0; + +	return clk->accuracy; +}  unsigned long __clk_get_flags(struct clk *clk)  { @@ -649,6 +693,7 @@ bool __clk_is_enabled(struct clk *clk)  out:  	return !!ret;  } +EXPORT_SYMBOL_GPL(__clk_is_enabled);  static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)  { @@ -740,6 +785,7 @@ out:  	return best;  } +EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);  /***        clk api        ***/ @@ -775,6 +821,9 @@ void __clk_unprepare(struct clk *clk)   */  void clk_unprepare(struct clk *clk)  { +	if (IS_ERR_OR_NULL(clk)) +		return; +  	clk_prepare_lock();  	__clk_unprepare(clk);  	clk_prepare_unlock(); @@ -836,9 +885,6 @@ static void __clk_disable(struct clk *clk)  	if (!clk)  		return; -	if (WARN_ON(IS_ERR(clk))) -		return; -  	if (WARN_ON(clk->enable_count == 0))  		return; @@ -867,6 +913,9 @@ void clk_disable(struct clk *clk)  {  	unsigned long flags; +	if (IS_ERR_OR_NULL(clk)) +		return; +  	flags = clk_enable_lock();  	__clk_disable(clk);  	clk_enable_unlock(flags); @@ -957,6 +1006,7 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)  	else  		return clk->rate;  } +EXPORT_SYMBOL_GPL(__clk_round_rate);  /**   * clk_round_rate - round the given rate for a clk @@ -1016,6 +1066,66 @@ static int __clk_notify(struct clk *clk, unsigned long msg,  }  /** + * __clk_recalc_accuracies + * @clk: 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 + * callback then it is assumed that the clock will take on the accuracy of it's + * parent. + * + * Caller must hold prepare_lock. + */ +static void __clk_recalc_accuracies(struct clk *clk) +{ +	unsigned long parent_accuracy = 0; +	struct clk *child; + +	if (clk->parent) +		parent_accuracy = clk->parent->accuracy; + +	if (clk->ops->recalc_accuracy) +		clk->accuracy = clk->ops->recalc_accuracy(clk->hw, +							  parent_accuracy); +	else +		clk->accuracy = parent_accuracy; + +	hlist_for_each_entry(child, &clk->children, child_node) +		__clk_recalc_accuracies(child); +} + +/** + * clk_get_accuracy - return the accuracy of clk + * @clk: the clk whose accuracy is being returned + * + * Simply returns the cached accuracy of the clk, unless + * CLK_GET_ACCURACY_NOCACHE flag is set, which means a recalc_rate will be + * issued. + * If clk is NULL then returns 0. + */ +long clk_get_accuracy(struct clk *clk) +{ +	unsigned long accuracy; + +	clk_prepare_lock(); +	if (clk && (clk->flags & CLK_GET_ACCURACY_NOCACHE)) +		__clk_recalc_accuracies(clk); + +	accuracy = __clk_get_accuracy(clk); +	clk_prepare_unlock(); + +	return accuracy; +} +EXPORT_SYMBOL_GPL(clk_get_accuracy); + +static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate) +{ +	if (clk->ops->recalc_rate) +		return clk->ops->recalc_rate(clk->hw, parent_rate); +	return parent_rate; +} + +/**   * __clk_recalc_rates   * @clk: first clk in the subtree   * @msg: notification type (see include/linux/clk.h) @@ -1040,10 +1150,7 @@ static void __clk_recalc_rates(struct clk *clk, unsigned long msg)  	if (clk->parent)  		parent_rate = clk->parent->rate; -	if (clk->ops->recalc_rate) -		clk->rate = clk->ops->recalc_rate(clk->hw, parent_rate); -	else -		clk->rate = parent_rate; +	clk->rate = clk_recalc(clk, parent_rate);  	/*  	 * ignore NOTIFY_STOP and NOTIFY_BAD return values for POST_RATE_CHANGE @@ -1080,13 +1187,16 @@ unsigned long clk_get_rate(struct clk *clk)  }  EXPORT_SYMBOL_GPL(clk_get_rate); -static u8 clk_fetch_parent_index(struct clk *clk, struct clk *parent) +static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)  { -	u8 i; +	int i; -	if (!clk->parents) -		clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents), -								GFP_KERNEL); +	if (!clk->parents) { +		clk->parents = kcalloc(clk->num_parents, +					sizeof(struct clk *), GFP_KERNEL); +		if (!clk->parents) +			return -ENOMEM; +	}  	/*  	 * find index of new parent clock using cached parent ptrs, @@ -1094,16 +1204,19 @@ static u8 clk_fetch_parent_index(struct clk *clk, struct clk *parent)  	 * them now to avoid future calls to __clk_lookup.  	 */  	for (i = 0; i < clk->num_parents; i++) { -		if (clk->parents && clk->parents[i] == parent) -			break; -		else if (!strcmp(clk->parent_names[i], parent->name)) { -			if (clk->parents) -				clk->parents[i] = __clk_lookup(parent->name); -			break; +		if (clk->parents[i] == parent) +			return i; + +		if (clk->parents[i]) +			continue; + +		if (!strcmp(clk->parent_names[i], parent->name)) { +			clk->parents[i] = __clk_lookup(parent->name); +			return i;  		}  	} -	return i; +	return -EINVAL;  }  static void clk_reparent(struct clk *clk, struct clk *new_parent) @@ -1123,10 +1236,9 @@ static void clk_reparent(struct clk *clk, struct clk *new_parent)  	clk->parent = new_parent;  } -static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) +static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)  {  	unsigned long flags; -	int ret = 0;  	struct clk *old_parent = clk->parent;  	/* @@ -1157,6 +1269,34 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)  	clk_reparent(clk, parent);  	clk_enable_unlock(flags); +	return old_parent; +} + +static void __clk_set_parent_after(struct clk *clk, struct clk *parent, +		struct clk *old_parent) +{ +	/* +	 * Finish the migration of prepare state and undo the changes done +	 * for preventing a race with clk_enable(). +	 */ +	if (clk->prepare_count) { +		clk_disable(clk); +		clk_disable(old_parent); +		__clk_unprepare(old_parent); +	} + +	/* update debugfs with new clk tree topology */ +	clk_debug_reparent(clk, parent); +} + +static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) +{ +	unsigned long flags; +	int ret = 0; +	struct clk *old_parent; + +	old_parent = __clk_set_parent_before(clk, parent); +  	/* change clock input source */  	if (parent && clk->ops->set_parent)  		ret = clk->ops->set_parent(clk->hw, p_index); @@ -1174,18 +1314,8 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)  		return ret;  	} -	/* -	 * Finish the migration of prepare state and undo the changes done -	 * for preventing a race with clk_enable(). -	 */ -	if (clk->prepare_count) { -		clk_disable(clk); -		clk_disable(old_parent); -		__clk_unprepare(old_parent); -	} +	__clk_set_parent_after(clk, parent, old_parent); -	/* update debugfs with new clk tree topology */ -	clk_debug_reparent(clk, parent);  	return 0;  } @@ -1211,17 +1341,17 @@ static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)  	unsigned long new_rate;  	int ret = NOTIFY_DONE; -	if (clk->ops->recalc_rate) -		new_rate = clk->ops->recalc_rate(clk->hw, parent_rate); -	else -		new_rate = parent_rate; +	new_rate = clk_recalc(clk, 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 (ret & NOTIFY_STOP_MASK) +	if (ret & NOTIFY_STOP_MASK) { +		pr_debug("%s: clk notifier callback for clock %s aborted with error %d\n", +				__func__, clk->name, ret);  		goto out; +	}  	hlist_for_each_entry(child, &clk->children, child_node) {  		ret = __clk_speculate_rates(child, new_rate); @@ -1247,10 +1377,7 @@ static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,  		new_parent->new_child = clk;  	hlist_for_each_entry(child, &clk->children, child_node) { -		if (child->ops->recalc_rate) -			child->new_rate = child->ops->recalc_rate(child->hw, new_rate); -		else -			child->new_rate = new_rate; +		child->new_rate = clk_recalc(child, new_rate);  		clk_calc_subtree(child, child->new_rate, NULL, 0);  	}  } @@ -1265,7 +1392,7 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)  	struct clk *old_parent, *parent;  	unsigned long best_parent_rate = 0;  	unsigned long new_rate; -	u8 p_index = 0; +	int p_index = 0;  	/* sanity */  	if (IS_ERR_OR_NULL(clk)) @@ -1306,7 +1433,7 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)  	/* try finding the new parent index */  	if (parent) {  		p_index = clk_fetch_parent_index(clk, parent); -		if (p_index == clk->num_parents) { +		if (p_index < 0) {  			pr_debug("%s: clk %s can not be parent of clk %s\n",  				 __func__, parent->name, clk->name);  			return NULL; @@ -1370,23 +1497,35 @@ static void clk_change_rate(struct clk *clk)  	struct clk *child;  	unsigned long old_rate;  	unsigned long best_parent_rate = 0; +	bool skip_set_rate = false; +	struct clk *old_parent;  	old_rate = clk->rate; -	/* set parent */ -	if (clk->new_parent && clk->new_parent != clk->parent) -		__clk_set_parent(clk, clk->new_parent, clk->new_parent_index); - -	if (clk->parent) +	if (clk->new_parent) +		best_parent_rate = clk->new_parent->rate; +	else if (clk->parent)  		best_parent_rate = clk->parent->rate; -	if (clk->ops->set_rate) +	if (clk->new_parent && clk->new_parent != clk->parent) { +		old_parent = __clk_set_parent_before(clk, clk->new_parent); + +		if (clk->ops->set_rate_and_parent) { +			skip_set_rate = true; +			clk->ops->set_rate_and_parent(clk->hw, clk->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); +		} + +		__clk_set_parent_after(clk, clk->new_parent, old_parent); +	} + +	if (!skip_set_rate && clk->ops->set_rate)  		clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate); -	if (clk->ops->recalc_rate) -		clk->rate = clk->ops->recalc_rate(clk->hw, best_parent_rate); -	else -		clk->rate = best_parent_rate; +	clk->rate = clk_recalc(clk, best_parent_rate);  	if (clk->notifier_count && old_rate != clk->rate)  		__clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); @@ -1454,7 +1593,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)  	/* notify that we are about to change rates */  	fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);  	if (fail_clk) { -		pr_warn("%s: failed to set %s rate\n", __func__, +		pr_debug("%s: failed to set %s rate\n", __func__,  				fail_clk->name);  		clk_propagate_rate_change(top, ABORT_RATE_CHANGE);  		ret = -EBUSY; @@ -1532,7 +1671,7 @@ static struct clk *__clk_init_parent(struct clk *clk)  	if (!clk->parents)  		clk->parents = -			kzalloc((sizeof(struct clk*) * clk->num_parents), +			kcalloc(clk->num_parents, sizeof(struct clk *),  					GFP_KERNEL);  	ret = clk_get_parent_by_index(clk, index); @@ -1545,6 +1684,7 @@ void __clk_reparent(struct clk *clk, struct clk *new_parent)  {  	clk_reparent(clk, new_parent);  	clk_debug_reparent(clk, new_parent); +	__clk_recalc_accuracies(clk);  	__clk_recalc_rates(clk, POST_RATE_CHANGE);  } @@ -1568,15 +1708,12 @@ void __clk_reparent(struct clk *clk, struct clk *new_parent)  int clk_set_parent(struct clk *clk, struct clk *parent)  {  	int ret = 0; -	u8 p_index = 0; +	int p_index = 0;  	unsigned long p_rate = 0;  	if (!clk)  		return 0; -	if (!clk->ops) -		return -EINVAL; -  	/* verify ops for for multi-parent clks */  	if ((clk->num_parents > 1) && (!clk->ops->set_parent))  		return -ENOSYS; @@ -1597,10 +1734,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent)  	if (parent) {  		p_index = clk_fetch_parent_index(clk, parent);  		p_rate = parent->rate; -		if (p_index == clk->num_parents) { +		if (p_index < 0) {  			pr_debug("%s: clk %s can not be parent of clk %s\n",  					__func__, parent->name, clk->name); -			ret = -EINVAL; +			ret = p_index;  			goto out;  		}  	} @@ -1615,11 +1752,13 @@ int clk_set_parent(struct clk *clk, struct clk *parent)  	/* do the re-parent */  	ret = __clk_set_parent(clk, parent, p_index); -	/* propagate rate recalculation accordingly */ -	if (ret) +	/* propagate rate an accuracy recalculation accordingly */ +	if (ret) {  		__clk_recalc_rates(clk, ABORT_RATE_CHANGE); -	else +	} else {  		__clk_recalc_rates(clk, POST_RATE_CHANGE); +		__clk_recalc_accuracies(clk); +	}  out:  	clk_prepare_unlock(); @@ -1672,6 +1811,14 @@ int __clk_init(struct device *dev, struct clk *clk)  		goto out;  	} +	if (clk->ops->set_rate_and_parent && +			!(clk->ops->set_parent && clk->ops->set_rate)) { +		pr_warn("%s: %s must implement .set_parent & .set_rate\n", +				__func__, clk->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], @@ -1689,8 +1836,8 @@ int __clk_init(struct device *dev, struct clk *clk)  	 * for clock drivers to statically initialize clk->parents.  	 */  	if (clk->num_parents > 1 && !clk->parents) { -		clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents), -				GFP_KERNEL); +		clk->parents = kcalloc(clk->num_parents, sizeof(struct clk *), +					GFP_KERNEL);  		/*  		 * __clk_lookup returns NULL for parents that have not been  		 * clk_init'd; thus any access to clk->parents[] must check @@ -1724,6 +1871,21 @@ int __clk_init(struct device *dev, struct clk *clk)  		hlist_add_head(&clk->child_node, &clk_orphan_list);  	/* +	 * Set clk's accuracy.  The preferred method is to use +	 * .recalc_accuracy. For simple clocks and lazy developers the default +	 * fallback is to use the parent's accuracy.  If a clock doesn't have a +	 * 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; +	else +		clk->accuracy = 0; + +	/*  	 * Set clk's rate.  The preferred method is to use .recalc_rate.  For  	 * simple clocks and lazy developers the default fallback is to use the  	 * parent's rate.  If a clock doesn't have a parent (or is orphaned) @@ -1737,6 +1899,7 @@ int __clk_init(struct device *dev, struct clk *clk)  	else  		clk->rate = 0; +	clk_debug_register(clk);  	/*  	 * walk the list of orphan clocks and reparent any that are children of  	 * this clock @@ -1767,8 +1930,7 @@ int __clk_init(struct device *dev, struct clk *clk)  	if (clk->ops->init)  		clk->ops->init(clk->hw); -	clk_debug_register(clk); - +	kref_init(&clk->ref);  out:  	clk_prepare_unlock(); @@ -1804,6 +1966,10 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw)  	clk->flags = hw->init->flags;  	clk->parent_names = hw->init->parent_names;  	clk->num_parents = hw->init->num_parents; +	if (dev && dev->driver) +		clk->owner = dev->driver->owner; +	else +		clk->owner = NULL;  	ret = __clk_init(dev, clk);  	if (ret) @@ -1813,9 +1979,28 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw)  }  EXPORT_SYMBOL_GPL(__clk_register); -static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk) +/** + * clk_register - allocate a new clock, register it and return an opaque cookie + * @dev: device that is registering this clock + * @hw: link to hardware-specific clock data + * + * 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 + * 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. + */ +struct clk *clk_register(struct device *dev, struct clk_hw *hw)  {  	int i, ret; +	struct clk *clk; + +	clk = kzalloc(sizeof(*clk), GFP_KERNEL); +	if (!clk) { +		pr_err("%s: could not allocate clk\n", __func__); +		ret = -ENOMEM; +		goto fail_out; +	}  	clk->name = kstrdup(hw->init->name, GFP_KERNEL);  	if (!clk->name) { @@ -1824,14 +2009,16 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)  		goto fail_name;  	}  	clk->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->clk = clk;  	/* allocate local copy in case parent_names is __initdata */ -	clk->parent_names = kzalloc((sizeof(char*) * clk->num_parents), -			GFP_KERNEL); +	clk->parent_names = kcalloc(clk->num_parents, sizeof(char *), +					GFP_KERNEL);  	if (!clk->parent_names) {  		pr_err("%s: could not allocate clk->parent_names\n", __func__); @@ -1853,7 +2040,7 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)  	ret = __clk_init(dev, clk);  	if (!ret) -		return 0; +		return clk;  fail_parent_names_copy:  	while (--i >= 0) @@ -1862,54 +2049,116 @@ fail_parent_names_copy:  fail_parent_names:  	kfree(clk->name);  fail_name: -	return ret; +	kfree(clk); +fail_out: +	return ERR_PTR(ret);  } +EXPORT_SYMBOL_GPL(clk_register); -/** - * clk_register - allocate a new clock, register it and return an opaque cookie - * @dev: device that is registering this clock - * @hw: link to hardware-specific clock data - * - * 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 - * 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. +/* + * Free memory allocated for a clock. + * Caller must hold prepare_lock.   */ -struct clk *clk_register(struct device *dev, struct clk_hw *hw) +static void __clk_release(struct kref *ref)  { -	int ret; -	struct clk *clk; - -	clk = kzalloc(sizeof(*clk), GFP_KERNEL); -	if (!clk) { -		pr_err("%s: could not allocate clk\n", __func__); -		ret = -ENOMEM; -		goto fail_out; -	} +	struct clk *clk = container_of(ref, struct clk, ref); +	int i = clk->num_parents; -	ret = _clk_register(dev, hw, clk); -	if (!ret) -		return clk; +	kfree(clk->parents); +	while (--i >= 0) +		kfree(clk->parent_names[i]); +	kfree(clk->parent_names); +	kfree(clk->name);  	kfree(clk); -fail_out: -	return ERR_PTR(ret);  } -EXPORT_SYMBOL_GPL(clk_register); + +/* + * Empty clk_ops for unregistered clocks. These are used temporarily + * after clk_unregister() was called on a clock and until last clock + * consumer calls clk_put() and the struct clk object is freed. + */ +static int clk_nodrv_prepare_enable(struct clk_hw *hw) +{ +	return -ENXIO; +} + +static void clk_nodrv_disable_unprepare(struct clk_hw *hw) +{ +	WARN_ON_ONCE(1); +} + +static int clk_nodrv_set_rate(struct clk_hw *hw, unsigned long rate, +					unsigned long parent_rate) +{ +	return -ENXIO; +} + +static int clk_nodrv_set_parent(struct clk_hw *hw, u8 index) +{ +	return -ENXIO; +} + +static const struct clk_ops clk_nodrv_ops = { +	.enable		= clk_nodrv_prepare_enable, +	.disable	= clk_nodrv_disable_unprepare, +	.prepare	= clk_nodrv_prepare_enable, +	.unprepare	= clk_nodrv_disable_unprepare, +	.set_rate	= clk_nodrv_set_rate, +	.set_parent	= clk_nodrv_set_parent, +};  /**   * clk_unregister - unregister a currently registered clock   * @clk: clock to unregister - * - * Currently unimplemented.   */ -void clk_unregister(struct clk *clk) {} +void clk_unregister(struct clk *clk) +{ +	unsigned long flags; + +       if (!clk || WARN_ON_ONCE(IS_ERR(clk))) +               return; + +	clk_prepare_lock(); + +	if (clk->ops == &clk_nodrv_ops) { +		pr_err("%s: unregistered clock: %s\n", __func__, clk->name); +		goto out; +	} +	/* +	 * Assign empty clock ops for consumers that might still hold +	 * a reference to this clock. +	 */ +	flags = clk_enable_lock(); +	clk->ops = &clk_nodrv_ops; +	clk_enable_unlock(flags); + +	if (!hlist_empty(&clk->children)) { +		struct clk *child; +		struct hlist_node *t; + +		/* Reparent all children to the orphan list. */ +		hlist_for_each_entry_safe(child, t, &clk->children, child_node) +			clk_set_parent(child, NULL); +	} + +	clk_debug_unregister(clk); + +	hlist_del_init(&clk->child_node); + +	if (clk->prepare_count) +		pr_warn("%s: unregistering prepared clock: %s\n", +					__func__, clk->name); + +	kref_put(&clk->ref, __clk_release); +out: +	clk_prepare_unlock(); +}  EXPORT_SYMBOL_GPL(clk_unregister);  static void devm_clk_release(struct device *dev, void *res)  { -	clk_unregister(res); +	clk_unregister(*(struct clk **)res);  }  /** @@ -1924,18 +2173,18 @@ static void devm_clk_release(struct device *dev, void *res)  struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)  {  	struct clk *clk; -	int ret; +	struct clk **clkp; -	clk = devres_alloc(devm_clk_release, sizeof(*clk), GFP_KERNEL); -	if (!clk) +	clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL); +	if (!clkp)  		return ERR_PTR(-ENOMEM); -	ret = _clk_register(dev, hw, clk); -	if (!ret) { -		devres_add(dev, clk); +	clk = clk_register(dev, hw); +	if (!IS_ERR(clk)) { +		*clkp = clk; +		devres_add(dev, clkp);  	} else { -		devres_free(clk); -		clk = ERR_PTR(ret); +		devres_free(clkp);  	}  	return clk; @@ -1964,6 +2213,32 @@ void devm_clk_unregister(struct device *dev, struct clk *clk)  }  EXPORT_SYMBOL_GPL(devm_clk_unregister); +/* + * clkdev helpers + */ +int __clk_get(struct clk *clk) +{ +	if (clk) { +		if (!try_module_get(clk->owner)) +			return 0; + +		kref_get(&clk->ref); +	} +	return 1; +} + +void __clk_put(struct clk *clk) +{ +	if (!clk || WARN_ON_ONCE(IS_ERR(clk))) +		return; + +	clk_prepare_lock(); +	kref_put(&clk->ref, __clk_release); +	clk_prepare_unlock(); + +	module_put(clk->owner); +} +  /***        clk rate change notifiers        ***/  /** @@ -1977,20 +2252,11 @@ EXPORT_SYMBOL_GPL(devm_clk_unregister);   * re-enter into the clk framework by calling any top-level clk APIs;   * this will cause a nested prepare_lock mutex.   * - * Pre-change notifier callbacks will be passed the current, pre-change - * rate of the clk via struct clk_notifier_data.old_rate.  The new, - * post-change rate of the clk is passed via struct - * clk_notifier_data.new_rate. - * - * Post-change notifiers will pass the now-current, post-change rate of - * the clk in both struct clk_notifier_data.old_rate and struct + * In all notification cases cases (pre, post and abort rate change) the + * original clock rate is passed to the callback via struct + * clk_notifier_data.old_rate and the new frequency is passed via struct   * clk_notifier_data.new_rate.   * - * Abort-change notifiers are effectively the opposite of pre-change - * notifiers: the original pre-change clk rate is passed in via struct - * clk_notifier_data.new_rate and the failed post-change rate is passed - * in via struct clk_notifier_data.old_rate. - *   * clk_notifier_register() must be called from non-atomic context.   * Returns -EINVAL if called with null arguments, -ENOMEM upon   * allocation failure; otherwise, passes along the return value of @@ -2098,13 +2364,22 @@ struct of_clk_provider {  	void *data;  }; -extern struct of_device_id __clk_of_table[]; -  static const struct of_device_id __clk_of_table_sentinel  	__used __section(__clk_of_table_end);  static LIST_HEAD(of_clk_providers); -static DEFINE_MUTEX(of_clk_lock); +static DEFINE_MUTEX(of_clk_mutex); + +/* of_clk_provider list locking helpers */ +void of_clk_lock(void) +{ +	mutex_lock(&of_clk_mutex); +} + +void of_clk_unlock(void) +{ +	mutex_unlock(&of_clk_mutex); +}  struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,  				     void *data) @@ -2148,9 +2423,9 @@ int of_clk_add_provider(struct device_node *np,  	cp->data = data;  	cp->get = clk_src_get; -	mutex_lock(&of_clk_lock); +	mutex_lock(&of_clk_mutex);  	list_add(&cp->link, &of_clk_providers); -	mutex_unlock(&of_clk_lock); +	mutex_unlock(&of_clk_mutex);  	pr_debug("Added clock from %s\n", np->full_name);  	return 0; @@ -2165,7 +2440,7 @@ void of_clk_del_provider(struct device_node *np)  {  	struct of_clk_provider *cp; -	mutex_lock(&of_clk_lock); +	mutex_lock(&of_clk_mutex);  	list_for_each_entry(cp, &of_clk_providers, link) {  		if (cp->node == np) {  			list_del(&cp->link); @@ -2174,33 +2449,52 @@ void of_clk_del_provider(struct device_node *np)  			break;  		}  	} -	mutex_unlock(&of_clk_lock); +	mutex_unlock(&of_clk_mutex);  }  EXPORT_SYMBOL_GPL(of_clk_del_provider); -struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) +struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec)  {  	struct of_clk_provider *provider; -	struct clk *clk = ERR_PTR(-ENOENT); +	struct clk *clk = ERR_PTR(-EPROBE_DEFER);  	/* Check if we have such a provider in our array */ -	mutex_lock(&of_clk_lock);  	list_for_each_entry(provider, &of_clk_providers, link) {  		if (provider->node == clkspec->np)  			clk = provider->get(clkspec, provider->data);  		if (!IS_ERR(clk))  			break;  	} -	mutex_unlock(&of_clk_lock);  	return clk;  } +struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) +{ +	struct clk *clk; + +	mutex_lock(&of_clk_mutex); +	clk = __of_clk_get_from_provider(clkspec); +	mutex_unlock(&of_clk_mutex); + +	return clk; +} + +int of_clk_get_parent_count(struct device_node *np) +{ +	return of_count_phandle_with_args(np, "clocks", "#clock-cells"); +} +EXPORT_SYMBOL_GPL(of_clk_get_parent_count); +  const char *of_clk_get_parent_name(struct device_node *np, int index)  {  	struct of_phandle_args clkspec; +	struct property *prop;  	const char *clk_name; +	const __be32 *vp; +	u32 pv;  	int rc; +	int count;  	if (index < 0)  		return NULL; @@ -2210,8 +2504,22 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)  	if (rc)  		return NULL; +	index = clkspec.args_count ? clkspec.args[0] : 0; +	count = 0; + +	/* if there is an indices property, use it to transfer the index +	 * specified into an array offset for the clock-output-names property. +	 */ +	of_property_for_each_u32(clkspec.np, "clock-indices", prop, vp, pv) { +		if (index == pv) { +			index = count; +			break; +		} +		count++; +	} +  	if (of_property_read_string_index(clkspec.np, "clock-output-names", -					  clkspec.args_count ? clkspec.args[0] : 0, +					  index,  					  &clk_name) < 0)  		clk_name = clkspec.np->name; @@ -2220,24 +2528,99 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)  }  EXPORT_SYMBOL_GPL(of_clk_get_parent_name); +struct clock_provider { +	of_clk_init_cb_t clk_init_cb; +	struct device_node *np; +	struct list_head node; +}; + +static LIST_HEAD(clk_provider_list); + +/* + * This function looks for a parent clock. If there is one, then it + * checks that the provider for this parent clock was initialized, in + * this case the parent clock will be ready. + */ +static int parent_ready(struct device_node *np) +{ +	int i = 0; + +	while (true) { +		struct clk *clk = of_clk_get(np, i); + +		/* this parent is ready we can check the next one */ +		if (!IS_ERR(clk)) { +			clk_put(clk); +			i++; +			continue; +		} + +		/* at least one parent is not ready, we exit now */ +		if (PTR_ERR(clk) == -EPROBE_DEFER) +			return 0; + +		/* +		 * Here we make assumption that the device tree is +		 * written correctly. So an error means that there is +		 * no more parent. As we didn't exit yet, then the +		 * previous parent are ready. If there is no clock +		 * parent, no need to wait for them, then we can +		 * consider their absence as being ready +		 */ +		return 1; +	} +} +  /**   * of_clk_init() - Scan and init clock providers from the DT   * @matches: array of compatible values and init functions for providers.   * - * This function scans the device tree for matching clock providers and - * calls their initialization functions + * This function scans the device tree for matching clock providers + * and calls their initialization functions. It also does it by trying + * to follow the dependencies.   */  void __init of_clk_init(const struct of_device_id *matches)  {  	const struct of_device_id *match;  	struct device_node *np; +	struct clock_provider *clk_provider, *next; +	bool is_init_done; +	bool force = false;  	if (!matches) -		matches = __clk_of_table; +		matches = &__clk_of_table; +	/* First prepare the list of the clocks providers */  	for_each_matching_node_and_match(np, matches, &match) { -		of_clk_init_cb_t clk_init_cb = match->data; -		clk_init_cb(np); +		struct clock_provider *parent = +			kzalloc(sizeof(struct clock_provider),	GFP_KERNEL); + +		parent->clk_init_cb = match->data; +		parent->np = np; +		list_add_tail(&parent->node, &clk_provider_list); +	} + +	while (!list_empty(&clk_provider_list)) { +		is_init_done = false; +		list_for_each_entry_safe(clk_provider, next, +					&clk_provider_list, node) { +			if (force || parent_ready(clk_provider->np)) { +				clk_provider->clk_init_cb(clk_provider->np); +				list_del(&clk_provider->node); +				kfree(clk_provider); +				is_init_done = true; +			} +		} + +		/* +		 * We didn't manage to initialize any of the +		 * remaining providers during the last loop, so now we +		 * initialize all the remaining ones unconditionally +		 * in case the clock parent was not mandatory +		 */ +		if (!is_init_done) +			force = true; +  	}  }  #endif  | 
