diff options
Diffstat (limited to 'drivers/devfreq/devfreq.c')
| -rw-r--r-- | drivers/devfreq/devfreq.c | 47 | 
1 files changed, 41 insertions, 6 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index a9fd61bbacf1..46517b61b3a2 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -316,6 +316,10 @@ static int devfreq_set_target(struct devfreq *devfreq, unsigned long new_freq,  			"Couldn't update frequency transition information.\n");  	devfreq->previous_freq = new_freq; + +	if (devfreq->suspend_freq) +		devfreq->resume_freq = cur_freq; +  	return err;  } @@ -667,6 +671,9 @@ struct devfreq *devfreq_add_device(struct device *dev,  	}  	devfreq->max_freq = devfreq->scaling_max_freq; +	devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev); +	atomic_set(&devfreq->suspend_count, 0); +  	dev_set_name(&devfreq->dev, "devfreq%d",  				atomic_inc_return(&devfreq_no));  	err = device_register(&devfreq->dev); @@ -867,14 +874,28 @@ EXPORT_SYMBOL(devm_devfreq_remove_device);   */  int devfreq_suspend_device(struct devfreq *devfreq)  { +	int ret; +  	if (!devfreq)  		return -EINVAL; -	if (!devfreq->governor) +	if (atomic_inc_return(&devfreq->suspend_count) > 1)  		return 0; -	return devfreq->governor->event_handler(devfreq, -				DEVFREQ_GOV_SUSPEND, NULL); +	if (devfreq->governor) { +		ret = devfreq->governor->event_handler(devfreq, +					DEVFREQ_GOV_SUSPEND, NULL); +		if (ret) +			return ret; +	} + +	if (devfreq->suspend_freq) { +		ret = devfreq_set_target(devfreq, devfreq->suspend_freq, 0); +		if (ret) +			return ret; +	} + +	return 0;  }  EXPORT_SYMBOL(devfreq_suspend_device); @@ -888,14 +909,28 @@ EXPORT_SYMBOL(devfreq_suspend_device);   */  int devfreq_resume_device(struct devfreq *devfreq)  { +	int ret; +  	if (!devfreq)  		return -EINVAL; -	if (!devfreq->governor) +	if (atomic_dec_return(&devfreq->suspend_count) >= 1)  		return 0; -	return devfreq->governor->event_handler(devfreq, -				DEVFREQ_GOV_RESUME, NULL); +	if (devfreq->resume_freq) { +		ret = devfreq_set_target(devfreq, devfreq->resume_freq, 0); +		if (ret) +			return ret; +	} + +	if (devfreq->governor) { +		ret = devfreq->governor->event_handler(devfreq, +					DEVFREQ_GOV_RESUME, NULL); +		if (ret) +			return ret; +	} + +	return 0;  }  EXPORT_SYMBOL(devfreq_resume_device);  | 
