aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/devfreq/devfreq.c
diff options
context:
space:
mode:
authorLukasz Luba <l.luba@partner.samsung.com>2018-12-05 06:05:53 -0500
committerMyungJoo Ham <myungjoo.ham@samsung.com>2018-12-10 21:09:47 -0500
commit83f8ca45afbf041e312909f442128b99657d90b7 (patch)
treed9f1ef6d6749aaaa6963cea58747a8024a24f61e /drivers/devfreq/devfreq.c
parent633141721b5bfce7017033a767208af591134b8f (diff)
PM / devfreq: add support for suspend/resume of a devfreq device
The patch prepares devfreq device for handling suspend/resume functionality. The new fields will store needed information during this process. Devfreq framework handles opp-suspend DT entry and there is no need of modyfications in the drivers code. It uses atomic variables to make sure no race condition affects the process. Suggested-by: Tobias Jakobi <tjakobi@math.uni-bielefeld.de> Suggested-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Lukasz Luba <l.luba@partner.samsung.com> Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Diffstat (limited to 'drivers/devfreq/devfreq.c')
-rw-r--r--drivers/devfreq/devfreq.c47
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,
316 "Couldn't update frequency transition information.\n"); 316 "Couldn't update frequency transition information.\n");
317 317
318 devfreq->previous_freq = new_freq; 318 devfreq->previous_freq = new_freq;
319
320 if (devfreq->suspend_freq)
321 devfreq->resume_freq = cur_freq;
322
319 return err; 323 return err;
320} 324}
321 325
@@ -667,6 +671,9 @@ struct devfreq *devfreq_add_device(struct device *dev,
667 } 671 }
668 devfreq->max_freq = devfreq->scaling_max_freq; 672 devfreq->max_freq = devfreq->scaling_max_freq;
669 673
674 devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
675 atomic_set(&devfreq->suspend_count, 0);
676
670 dev_set_name(&devfreq->dev, "devfreq%d", 677 dev_set_name(&devfreq->dev, "devfreq%d",
671 atomic_inc_return(&devfreq_no)); 678 atomic_inc_return(&devfreq_no));
672 err = device_register(&devfreq->dev); 679 err = device_register(&devfreq->dev);
@@ -867,14 +874,28 @@ EXPORT_SYMBOL(devm_devfreq_remove_device);
867 */ 874 */
868int devfreq_suspend_device(struct devfreq *devfreq) 875int devfreq_suspend_device(struct devfreq *devfreq)
869{ 876{
877 int ret;
878
870 if (!devfreq) 879 if (!devfreq)
871 return -EINVAL; 880 return -EINVAL;
872 881
873 if (!devfreq->governor) 882 if (atomic_inc_return(&devfreq->suspend_count) > 1)
874 return 0; 883 return 0;
875 884
876 return devfreq->governor->event_handler(devfreq, 885 if (devfreq->governor) {
877 DEVFREQ_GOV_SUSPEND, NULL); 886 ret = devfreq->governor->event_handler(devfreq,
887 DEVFREQ_GOV_SUSPEND, NULL);
888 if (ret)
889 return ret;
890 }
891
892 if (devfreq->suspend_freq) {
893 ret = devfreq_set_target(devfreq, devfreq->suspend_freq, 0);
894 if (ret)
895 return ret;
896 }
897
898 return 0;
878} 899}
879EXPORT_SYMBOL(devfreq_suspend_device); 900EXPORT_SYMBOL(devfreq_suspend_device);
880 901
@@ -888,14 +909,28 @@ EXPORT_SYMBOL(devfreq_suspend_device);
888 */ 909 */
889int devfreq_resume_device(struct devfreq *devfreq) 910int devfreq_resume_device(struct devfreq *devfreq)
890{ 911{
912 int ret;
913
891 if (!devfreq) 914 if (!devfreq)
892 return -EINVAL; 915 return -EINVAL;
893 916
894 if (!devfreq->governor) 917 if (atomic_dec_return(&devfreq->suspend_count) >= 1)
895 return 0; 918 return 0;
896 919
897 return devfreq->governor->event_handler(devfreq, 920 if (devfreq->resume_freq) {
898 DEVFREQ_GOV_RESUME, NULL); 921 ret = devfreq_set_target(devfreq, devfreq->resume_freq, 0);
922 if (ret)
923 return ret;
924 }
925
926 if (devfreq->governor) {
927 ret = devfreq->governor->event_handler(devfreq,
928 DEVFREQ_GOV_RESUME, NULL);
929 if (ret)
930 return ret;
931 }
932
933 return 0;
899} 934}
900EXPORT_SYMBOL(devfreq_resume_device); 935EXPORT_SYMBOL(devfreq_resume_device);
901 936