summaryrefslogtreecommitdiffstats
path: root/drivers/devfreq/devfreq.c
diff options
context:
space:
mode:
authorMyungJoo Ham <myungjoo.ham@samsung.com>2012-03-16 21:54:53 +0100
committerRafael J. Wysocki <rjw@sisk.pl>2012-03-17 21:51:34 +0100
commitab5f299f51259fd2466cf35c89d79bd960e0fc32 (patch)
tree2c8b409511e48e04833b57457acdb98207201b0b /drivers/devfreq/devfreq.c
parente4c9d8efe6bdc844071d68960dfa2003c5cf6449 (diff)
downloadop-kernel-dev-ab5f299f51259fd2466cf35c89d79bd960e0fc32.zip
op-kernel-dev-ab5f299f51259fd2466cf35c89d79bd960e0fc32.tar.gz
PM / devfreq: add relation of recommended frequency.
The semantics of "target frequency" given to devfreq driver from devfreq framework has always been interpretted as "at least" or GLB (greatest lower bound). However, the framework might want the device driver to limit its max frequency (LUB: least upper bound), especially if it is given by thermal framework (it's too hot). Thus, the target fuction should have another parameter to express whether the framework wants GLB or LUB. And, the additional parameter, "u32 flags", does it. With the update, devfreq_recommended_opp() is also updated. Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Reviewed-by: Mike Turquette <mturquette@ti.com> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/devfreq/devfreq.c')
-rw-r--r--drivers/devfreq/devfreq.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index a129a7b..70c31d4 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -83,6 +83,7 @@ int update_devfreq(struct devfreq *devfreq)
{
unsigned long freq;
int err = 0;
+ u32 flags = 0;
if (!mutex_is_locked(&devfreq->lock)) {
WARN(true, "devfreq->lock must be locked by the caller.\n");
@@ -94,7 +95,24 @@ int update_devfreq(struct devfreq *devfreq)
if (err)
return err;
- err = devfreq->profile->target(devfreq->dev.parent, &freq);
+ /*
+ * Adjust the freuqency with user freq and QoS.
+ *
+ * List from the highest proiority
+ * max_freq (probably called by thermal when it's too hot)
+ * min_freq
+ */
+
+ if (devfreq->min_freq && freq < devfreq->min_freq) {
+ freq = devfreq->min_freq;
+ flags &= ~DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use GLB */
+ }
+ if (devfreq->max_freq && freq > devfreq->max_freq) {
+ freq = devfreq->max_freq;
+ flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */
+ }
+
+ err = devfreq->profile->target(devfreq->dev.parent, &freq, flags);
if (err)
return err;
@@ -625,14 +643,30 @@ module_exit(devfreq_exit);
* freq value given to target callback.
* @dev The devfreq user device. (parent of devfreq)
* @freq The frequency given to target function
+ * @flags Flags handed from devfreq framework.
*
*/
-struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq)
+struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
+ u32 flags)
{
- struct opp *opp = opp_find_freq_ceil(dev, freq);
+ struct opp *opp;
- if (opp == ERR_PTR(-ENODEV))
+ if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) {
+ /* The freq is an upper bound. opp should be lower */
opp = opp_find_freq_floor(dev, freq);
+
+ /* If not available, use the closest opp */
+ if (opp == ERR_PTR(-ENODEV))
+ opp = opp_find_freq_ceil(dev, freq);
+ } else {
+ /* The freq is an lower bound. opp should be higher */
+ opp = opp_find_freq_ceil(dev, freq);
+
+ /* If not available, use the closest opp */
+ if (opp == ERR_PTR(-ENODEV))
+ opp = opp_find_freq_floor(dev, freq);
+ }
+
return opp;
}
OpenPOWER on IntegriCloud