]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'pm-devfreq'
authorRafael J. Wysocki <rjw@sisk.pl>
Sun, 4 Mar 2012 22:10:46 +0000 (23:10 +0100)
committerRafael J. Wysocki <rjw@sisk.pl>
Sun, 4 Mar 2012 22:10:46 +0000 (23:10 +0100)
* pm-devfreq:
  PM / devfreq: add min/max_freq limit requested by users.
  PM / devfreq: fixed syntax errors.
  devfreq: Remove MODULE_ALIAS for exynos4 busfreq driver
  devfreq: exynos4_bus: Use dev_get_drvdata at appropriate places

drivers/devfreq/devfreq.c
drivers/devfreq/exynos4_bus.c
drivers/devfreq/governor_performance.c
drivers/devfreq/governor_powersave.c
drivers/devfreq/governor_simpleondemand.c
drivers/devfreq/governor_userspace.c
include/linux/devfreq.h

index c189b82f5ececeddc29f97e62bc948ffb3f31961..a129a7b6bfd121a603f401053bbe0a11865ce03a 100644 (file)
@@ -501,12 +501,82 @@ static ssize_t show_central_polling(struct device *dev,
                       !to_devfreq(dev)->governor->no_central_polling);
 }
 
+static ssize_t store_min_freq(struct device *dev, struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct devfreq *df = to_devfreq(dev);
+       unsigned long value;
+       int ret;
+       unsigned long max;
+
+       ret = sscanf(buf, "%lu", &value);
+       if (ret != 1)
+               goto out;
+
+       mutex_lock(&df->lock);
+       max = df->max_freq;
+       if (value && max && value > max) {
+               ret = -EINVAL;
+               goto unlock;
+       }
+
+       df->min_freq = value;
+       update_devfreq(df);
+       ret = count;
+unlock:
+       mutex_unlock(&df->lock);
+out:
+       return ret;
+}
+
+static ssize_t show_min_freq(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       return sprintf(buf, "%lu\n", to_devfreq(dev)->min_freq);
+}
+
+static ssize_t store_max_freq(struct device *dev, struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct devfreq *df = to_devfreq(dev);
+       unsigned long value;
+       int ret;
+       unsigned long min;
+
+       ret = sscanf(buf, "%lu", &value);
+       if (ret != 1)
+               goto out;
+
+       mutex_lock(&df->lock);
+       min = df->min_freq;
+       if (value && min && value < min) {
+               ret = -EINVAL;
+               goto unlock;
+       }
+
+       df->max_freq = value;
+       update_devfreq(df);
+       ret = count;
+unlock:
+       mutex_unlock(&df->lock);
+out:
+       return ret;
+}
+
+static ssize_t show_max_freq(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq);
+}
+
 static struct device_attribute devfreq_attrs[] = {
        __ATTR(governor, S_IRUGO, show_governor, NULL),
        __ATTR(cur_freq, S_IRUGO, show_freq, NULL),
        __ATTR(central_polling, S_IRUGO, show_central_polling, NULL),
        __ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval,
               store_polling_interval),
+       __ATTR(min_freq, S_IRUGO | S_IWUSR, show_min_freq, store_min_freq),
+       __ATTR(max_freq, S_IRUGO | S_IWUSR, show_max_freq, store_max_freq),
        { },
 };
 
index 6460577d6701b468bd6edeaa1c21e739b7818918..590d6865e388e4b52ba41a7c4c2093508b870746 100644 (file)
@@ -622,9 +622,7 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp,
 static int exynos4_bus_target(struct device *dev, unsigned long *_freq)
 {
        int err = 0;
-       struct platform_device *pdev = container_of(dev, struct platform_device,
-                                                   dev);
-       struct busfreq_data *data = platform_get_drvdata(pdev);
+       struct busfreq_data *data = dev_get_drvdata(dev);
        struct opp *opp = devfreq_recommended_opp(dev, _freq);
        unsigned long old_freq = opp_get_freq(data->curr_opp);
        unsigned long freq = opp_get_freq(opp);
@@ -689,9 +687,7 @@ static int exynos4_get_busier_dmc(struct busfreq_data *data)
 static int exynos4_bus_get_dev_status(struct device *dev,
                                      struct devfreq_dev_status *stat)
 {
-       struct platform_device *pdev = container_of(dev, struct platform_device,
-                                                   dev);
-       struct busfreq_data *data = platform_get_drvdata(pdev);
+       struct busfreq_data *data = dev_get_drvdata(dev);
        int busier_dmc;
        int cycles_x2 = 2; /* 2 x cycles */
        void __iomem *addr;
@@ -739,9 +735,7 @@ static int exynos4_bus_get_dev_status(struct device *dev,
 
 static void exynos4_bus_exit(struct device *dev)
 {
-       struct platform_device *pdev = container_of(dev, struct platform_device,
-                                                   dev);
-       struct busfreq_data *data = platform_get_drvdata(pdev);
+       struct busfreq_data *data = dev_get_drvdata(dev);
 
        devfreq_unregister_opp_notifier(dev, data->devfreq);
 }
@@ -1087,9 +1081,7 @@ static __devexit int exynos4_busfreq_remove(struct platform_device *pdev)
 
 static int exynos4_busfreq_resume(struct device *dev)
 {
-       struct platform_device *pdev = container_of(dev, struct platform_device,
-                                                   dev);
-       struct busfreq_data *data = platform_get_drvdata(pdev);
+       struct busfreq_data *data = dev_get_drvdata(dev);
 
        busfreq_mon_reset(data);
        return 0;
@@ -1132,4 +1124,3 @@ module_exit(exynos4_busfreq_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("EXYNOS4 busfreq driver with devfreq framework");
 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
-MODULE_ALIAS("exynos4-busfreq");
index c0596b29176113653a59c1993477f8b5a7e0c6aa..574a06b1b1deb4d431cddd1d7a399bcb9a7825f4 100644 (file)
@@ -18,7 +18,10 @@ static int devfreq_performance_func(struct devfreq *df,
         * target callback should be able to get floor value as
         * said in devfreq.h
         */
-       *freq = UINT_MAX;
+       if (!df->max_freq)
+               *freq = UINT_MAX;
+       else
+               *freq = df->max_freq;
        return 0;
 }
 
index 2483a85a266fad446a39ae806438c952b0e9248b..d742d4a82d6a0da726f620ae5505e4d5c642c95b 100644 (file)
@@ -18,7 +18,7 @@ static int devfreq_powersave_func(struct devfreq *df,
         * target callback should be able to get ceiling value as
         * said in devfreq.h
         */
-       *freq = 0;
+       *freq = df->min_freq;
        return 0;
 }
 
index efad8dcf902877f4b67e5179dbd1dc17ba695abb..a2e3eae790119ef7e01527a94b4bf44b20589a07 100644 (file)
@@ -25,6 +25,7 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
        unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD;
        unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL;
        struct devfreq_simple_ondemand_data *data = df->data;
+       unsigned long max = (df->max_freq) ? df->max_freq : UINT_MAX;
 
        if (err)
                return err;
@@ -41,7 +42,7 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
 
        /* Assume MAX if it is going to be divided by zero */
        if (stat.total_time == 0) {
-               *freq = UINT_MAX;
+               *freq = max;
                return 0;
        }
 
@@ -54,13 +55,13 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
        /* Set MAX if it's busy enough */
        if (stat.busy_time * 100 >
            stat.total_time * dfso_upthreshold) {
-               *freq = UINT_MAX;
+               *freq = max;
                return 0;
        }
 
        /* Set MAX if we do not know the initial frequency */
        if (stat.current_frequency == 0) {
-               *freq = UINT_MAX;
+               *freq = max;
                return 0;
        }
 
@@ -79,6 +80,11 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
        b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2));
        *freq = (unsigned long) b;
 
+       if (df->min_freq && *freq < df->min_freq)
+               *freq = df->min_freq;
+       if (df->max_freq && *freq > df->max_freq)
+               *freq = df->max_freq;
+
        return 0;
 }
 
index 4f8b563da78265debbe968690b37707b91e39fd1..0681246fc89dc32e53900929abd2c2df4329e0ab 100644 (file)
@@ -25,10 +25,19 @@ static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq)
 {
        struct userspace_data *data = df->data;
 
-       if (!data->valid)
+       if (data->valid) {
+               unsigned long adjusted_freq = data->user_frequency;
+
+               if (df->max_freq && adjusted_freq > df->max_freq)
+                       adjusted_freq = df->max_freq;
+
+               if (df->min_freq && adjusted_freq < df->min_freq)
+                       adjusted_freq = df->min_freq;
+
+               *freq = adjusted_freq;
+       } else {
                *freq = df->previous_freq; /* No user freq specified yet */
-       else
-               *freq = data->user_frequency;
+       }
        return 0;
 }
 
index 98ce8124b1cc5e5fb2e61fcf89cc8bd3cc0a7e82..5862475d05f8a4110400fe29f1eb6f5d73a0596c 100644 (file)
@@ -124,6 +124,8 @@ struct devfreq_governor {
  *             touch this.
  * @being_removed      a flag to mark that this object is being removed in
  *                     order to prevent trying to remove the object multiple times.
+ * @min_freq   Limit minimum frequency requested by user (0: none)
+ * @max_freq   Limit maximum frequency requested by user (0: none)
  *
  * This structure stores the devfreq information for a give device.
  *
@@ -149,6 +151,9 @@ struct devfreq {
        void *data; /* private data for governors */
 
        bool being_removed;
+
+       unsigned long min_freq;
+       unsigned long max_freq;
 };
 
 #if defined(CONFIG_PM_DEVFREQ)
@@ -200,12 +205,12 @@ struct devfreq_simple_ondemand_data {
 static struct devfreq *devfreq_add_device(struct device *dev,
                                          struct devfreq_dev_profile *profile,
                                          struct devfreq_governor *governor,
-                                         void *data);
+                                         void *data)
 {
        return NULL;
 }
 
-static int devfreq_remove_device(struct devfreq *devfreq);
+static int devfreq_remove_device(struct devfreq *devfreq)
 {
        return 0;
 }