aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/devfreq/devfreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/devfreq/devfreq.c')
-rw-r--r--drivers/devfreq/devfreq.c112
1 files changed, 108 insertions, 4 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index c189b82f5ece..70c31d43fff3 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -83,6 +83,7 @@ int update_devfreq(struct devfreq *devfreq)
83{ 83{
84 unsigned long freq; 84 unsigned long freq;
85 int err = 0; 85 int err = 0;
86 u32 flags = 0;
86 87
87 if (!mutex_is_locked(&devfreq->lock)) { 88 if (!mutex_is_locked(&devfreq->lock)) {
88 WARN(true, "devfreq->lock must be locked by the caller.\n"); 89 WARN(true, "devfreq->lock must be locked by the caller.\n");
@@ -94,7 +95,24 @@ int update_devfreq(struct devfreq *devfreq)
94 if (err) 95 if (err)
95 return err; 96 return err;
96 97
97 err = devfreq->profile->target(devfreq->dev.parent, &freq); 98 /*
99 * Adjust the freuqency with user freq and QoS.
100 *
101 * List from the highest proiority
102 * max_freq (probably called by thermal when it's too hot)
103 * min_freq
104 */
105
106 if (devfreq->min_freq && freq < devfreq->min_freq) {
107 freq = devfreq->min_freq;
108 flags &= ~DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use GLB */
109 }
110 if (devfreq->max_freq && freq > devfreq->max_freq) {
111 freq = devfreq->max_freq;
112 flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */
113 }
114
115 err = devfreq->profile->target(devfreq->dev.parent, &freq, flags);
98 if (err) 116 if (err)
99 return err; 117 return err;
100 118
@@ -501,12 +519,82 @@ static ssize_t show_central_polling(struct device *dev,
501 !to_devfreq(dev)->governor->no_central_polling); 519 !to_devfreq(dev)->governor->no_central_polling);
502} 520}
503 521
522static ssize_t store_min_freq(struct device *dev, struct device_attribute *attr,
523 const char *buf, size_t count)
524{
525 struct devfreq *df = to_devfreq(dev);
526 unsigned long value;
527 int ret;
528 unsigned long max;
529
530 ret = sscanf(buf, "%lu", &value);
531 if (ret != 1)
532 goto out;
533
534 mutex_lock(&df->lock);
535 max = df->max_freq;
536 if (value && max && value > max) {
537 ret = -EINVAL;
538 goto unlock;
539 }
540
541 df->min_freq = value;
542 update_devfreq(df);
543 ret = count;
544unlock:
545 mutex_unlock(&df->lock);
546out:
547 return ret;
548}
549
550static ssize_t show_min_freq(struct device *dev, struct device_attribute *attr,
551 char *buf)
552{
553 return sprintf(buf, "%lu\n", to_devfreq(dev)->min_freq);
554}
555
556static ssize_t store_max_freq(struct device *dev, struct device_attribute *attr,
557 const char *buf, size_t count)
558{
559 struct devfreq *df = to_devfreq(dev);
560 unsigned long value;
561 int ret;
562 unsigned long min;
563
564 ret = sscanf(buf, "%lu", &value);
565 if (ret != 1)
566 goto out;
567
568 mutex_lock(&df->lock);
569 min = df->min_freq;
570 if (value && min && value < min) {
571 ret = -EINVAL;
572 goto unlock;
573 }
574
575 df->max_freq = value;
576 update_devfreq(df);
577 ret = count;
578unlock:
579 mutex_unlock(&df->lock);
580out:
581 return ret;
582}
583
584static ssize_t show_max_freq(struct device *dev, struct device_attribute *attr,
585 char *buf)
586{
587 return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq);
588}
589
504static struct device_attribute devfreq_attrs[] = { 590static struct device_attribute devfreq_attrs[] = {
505 __ATTR(governor, S_IRUGO, show_governor, NULL), 591 __ATTR(governor, S_IRUGO, show_governor, NULL),
506 __ATTR(cur_freq, S_IRUGO, show_freq, NULL), 592 __ATTR(cur_freq, S_IRUGO, show_freq, NULL),
507 __ATTR(central_polling, S_IRUGO, show_central_polling, NULL), 593 __ATTR(central_polling, S_IRUGO, show_central_polling, NULL),
508 __ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval, 594 __ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval,
509 store_polling_interval), 595 store_polling_interval),
596 __ATTR(min_freq, S_IRUGO | S_IWUSR, show_min_freq, store_min_freq),
597 __ATTR(max_freq, S_IRUGO | S_IWUSR, show_max_freq, store_max_freq),
510 { }, 598 { },
511}; 599};
512 600
@@ -555,14 +643,30 @@ module_exit(devfreq_exit);
555 * freq value given to target callback. 643 * freq value given to target callback.
556 * @dev The devfreq user device. (parent of devfreq) 644 * @dev The devfreq user device. (parent of devfreq)
557 * @freq The frequency given to target function 645 * @freq The frequency given to target function
646 * @flags Flags handed from devfreq framework.
558 * 647 *
559 */ 648 */
560struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq) 649struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
650 u32 flags)
561{ 651{
562 struct opp *opp = opp_find_freq_ceil(dev, freq); 652 struct opp *opp;
563 653
564 if (opp == ERR_PTR(-ENODEV)) 654 if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) {
655 /* The freq is an upper bound. opp should be lower */
565 opp = opp_find_freq_floor(dev, freq); 656 opp = opp_find_freq_floor(dev, freq);
657
658 /* If not available, use the closest opp */
659 if (opp == ERR_PTR(-ENODEV))
660 opp = opp_find_freq_ceil(dev, freq);
661 } else {
662 /* The freq is an lower bound. opp should be higher */
663 opp = opp_find_freq_ceil(dev, freq);
664
665 /* If not available, use the closest opp */
666 if (opp == ERR_PTR(-ENODEV))
667 opp = opp_find_freq_floor(dev, freq);
668 }
669
566 return opp; 670 return opp;
567} 671}
568 672