diff options
Diffstat (limited to 'drivers/sh/clk')
| -rw-r--r-- | drivers/sh/clk/core.c | 38 | 
1 files changed, 30 insertions, 8 deletions
| diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c index 4f64183b27fa..dc8d022c07a1 100644 --- a/drivers/sh/clk/core.c +++ b/drivers/sh/clk/core.c @@ -34,6 +34,9 @@ static LIST_HEAD(clock_list);  static DEFINE_SPINLOCK(clock_lock);  static DEFINE_MUTEX(clock_list_sem); +/* clock disable operations are not passed on to hardware during boot */ +static int allow_disable; +  void clk_rate_table_build(struct clk *clk,  			  struct cpufreq_frequency_table *freq_table,  			  int nr_freqs, @@ -228,7 +231,7 @@ static void __clk_disable(struct clk *clk)  		return;  	if (!(--clk->usecount)) { -		if (likely(clk->ops && clk->ops->disable)) +		if (likely(allow_disable && clk->ops && clk->ops->disable))  			clk->ops->disable(clk);  		if (likely(clk->parent))  			__clk_disable(clk->parent); @@ -393,7 +396,7 @@ int clk_register(struct clk *clk)  {  	int ret; -	if (clk == NULL || IS_ERR(clk)) +	if (IS_ERR_OR_NULL(clk))  		return -EINVAL;  	/* @@ -635,7 +638,7 @@ static void clks_core_resume(void)  	struct clk *clkp;  	list_for_each_entry(clkp, &clock_list, node) { -		if (likely(clkp->ops)) { +		if (likely(clkp->usecount && clkp->ops)) {  			unsigned long rate = clkp->rate;  			if (likely(clkp->ops->set_parent)) @@ -670,7 +673,7 @@ static struct dentry *clk_debugfs_root;  static int clk_debugfs_register_one(struct clk *c)  {  	int err; -	struct dentry *d, *child, *child_tmp; +	struct dentry *d;  	struct clk *pa = c->parent;  	char s[255];  	char *p = s; @@ -699,10 +702,7 @@ static int clk_debugfs_register_one(struct clk *c)  	return 0;  err_out: -	d = c->dentry; -	list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) -		debugfs_remove(child); -	debugfs_remove(c->dentry); +	debugfs_remove_recursive(c->dentry);  	return err;  } @@ -747,3 +747,25 @@ err_out:  	return err;  }  late_initcall(clk_debugfs_init); + +static int __init clk_late_init(void) +{ +	unsigned long flags; +	struct clk *clk; + +	/* disable all clocks with zero use count */ +	mutex_lock(&clock_list_sem); +	spin_lock_irqsave(&clock_lock, flags); + +	list_for_each_entry(clk, &clock_list, node) +		if (!clk->usecount && clk->ops && clk->ops->disable) +			clk->ops->disable(clk); + +	/* from now on allow clock disable operations */ +	allow_disable = 1; + +	spin_unlock_irqrestore(&clock_lock, flags); +	mutex_unlock(&clock_list_sem); +	return 0; +} +late_initcall(clk_late_init); | 
