diff options
Diffstat (limited to 'drivers/base/power/clock_ops.c')
| -rw-r--r-- | drivers/base/power/clock_ops.c | 76 | 
1 files changed, 39 insertions, 37 deletions
diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index cb44b58d681..b876e60a53e 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -32,6 +32,22 @@ struct pm_clock_entry {  };  /** + * pm_clk_acquire - Acquire a device clock. + * @dev: Device whose clock is to be acquired. + * @ce: PM clock entry corresponding to the clock. + */ +static void pm_clk_acquire(struct device *dev, struct pm_clock_entry *ce) +{ +	ce->clk = clk_get(dev, ce->con_id); +	if (IS_ERR(ce->clk)) { +		ce->status = PCE_STATUS_ERROR; +	} else { +		ce->status = PCE_STATUS_ACQUIRED; +		dev_dbg(dev, "Clock %s managed by runtime PM.\n", ce->con_id); +	} +} + +/**   * pm_clk_add - Start using a device clock for power management.   * @dev: Device whose clock is going to be used for power management.   * @con_id: Connection ID of the clock. @@ -63,6 +79,8 @@ int pm_clk_add(struct device *dev, const char *con_id)  		}  	} +	pm_clk_acquire(dev, ce); +  	spin_lock_irq(&psd->lock);  	list_add_tail(&ce->node, &psd->clock_list);  	spin_unlock_irq(&psd->lock); @@ -72,17 +90,12 @@ int pm_clk_add(struct device *dev, const char *con_id)  /**   * __pm_clk_remove - Destroy PM clock entry.   * @ce: PM clock entry to destroy. - * - * This routine must be called under the spinlock protecting the PM list of - * clocks corresponding the the @ce's device.   */  static void __pm_clk_remove(struct pm_clock_entry *ce)  {  	if (!ce)  		return; -	list_del(&ce->node); -  	if (ce->status < PCE_STATUS_ERROR) {  		if (ce->status == PCE_STATUS_ENABLED)  			clk_disable(ce->clk); @@ -116,18 +129,22 @@ void pm_clk_remove(struct device *dev, const char *con_id)  	spin_lock_irq(&psd->lock);  	list_for_each_entry(ce, &psd->clock_list, node) { -		if (!con_id && !ce->con_id) { -			__pm_clk_remove(ce); -			break; -		} else if (!con_id || !ce->con_id) { +		if (!con_id && !ce->con_id) +			goto remove; +		else if (!con_id || !ce->con_id)  			continue; -		} else if (!strcmp(con_id, ce->con_id)) { -			__pm_clk_remove(ce); -			break; -		} +		else if (!strcmp(con_id, ce->con_id)) +			goto remove;  	}  	spin_unlock_irq(&psd->lock); +	return; + + remove: +	list_del(&ce->node); +	spin_unlock_irq(&psd->lock); + +	__pm_clk_remove(ce);  }  /** @@ -169,18 +186,26 @@ void pm_clk_destroy(struct device *dev)  {  	struct pm_subsys_data *psd = dev_to_psd(dev);  	struct pm_clock_entry *ce, *c; +	struct list_head list;  	if (!psd)  		return; +	INIT_LIST_HEAD(&list); +  	spin_lock_irq(&psd->lock);  	list_for_each_entry_safe_reverse(ce, c, &psd->clock_list, node) -		__pm_clk_remove(ce); +		list_move(&ce->node, &list);  	spin_unlock_irq(&psd->lock);  	dev_pm_put_subsys_data(dev); + +	list_for_each_entry_safe_reverse(ce, c, &list, node) { +		list_del(&ce->node); +		__pm_clk_remove(ce); +	}  }  #endif /* CONFIG_PM */ @@ -188,23 +213,6 @@ void pm_clk_destroy(struct device *dev)  #ifdef CONFIG_PM_RUNTIME  /** - * pm_clk_acquire - Acquire a device clock. - * @dev: Device whose clock is to be acquired. - * @con_id: Connection ID of the clock. - */ -static void pm_clk_acquire(struct device *dev, -				    struct pm_clock_entry *ce) -{ -	ce->clk = clk_get(dev, ce->con_id); -	if (IS_ERR(ce->clk)) { -		ce->status = PCE_STATUS_ERROR; -	} else { -		ce->status = PCE_STATUS_ACQUIRED; -		dev_dbg(dev, "Clock %s managed by runtime PM.\n", ce->con_id); -	} -} - -/**   * pm_clk_suspend - Disable clocks in a device's PM clock list.   * @dev: Device to disable the clocks for.   */ @@ -222,9 +230,6 @@ int pm_clk_suspend(struct device *dev)  	spin_lock_irqsave(&psd->lock, flags);  	list_for_each_entry_reverse(ce, &psd->clock_list, node) { -		if (ce->status == PCE_STATUS_NONE) -			pm_clk_acquire(dev, ce); -  		if (ce->status < PCE_STATUS_ERROR) {  			clk_disable(ce->clk);  			ce->status = PCE_STATUS_ACQUIRED; @@ -254,9 +259,6 @@ int pm_clk_resume(struct device *dev)  	spin_lock_irqsave(&psd->lock, flags);  	list_for_each_entry(ce, &psd->clock_list, node) { -		if (ce->status == PCE_STATUS_NONE) -			pm_clk_acquire(dev, ce); -  		if (ce->status < PCE_STATUS_ERROR) {  			clk_enable(ce->clk);  			ce->status = PCE_STATUS_ENABLED;  |