PM / devfreq: Add common sysfs interfaces
authorMyungJoo Ham <myungjoo.ham@samsung.com>
Sat, 1 Oct 2011 22:19:28 +0000 (00:19 +0200)
committerRafael J. Wysocki <rjw@sisk.pl>
Sat, 1 Oct 2011 22:19:28 +0000 (00:19 +0200)
Device specific sysfs interface /sys/devices/.../power/devfreq_*
- governor R: name of governor
- cur_freq R: current frequency
- polling_interval R: polling interval in ms given with devfreq profile
W: update polling interval.
- central_polling R: 1 if polling is managed by devfreq framework

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>
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
--
 Documentation/ABI/testing/sysfs-class-devfreq |   44 ++++++++++++++++
 drivers/devfreq/devfreq.c                     |   69 ++++++++++++++++++++++++++
 2 files changed, 113 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-class-devfreq

Documentation/ABI/testing/sysfs-class-devfreq [new file with mode: 0644]
drivers/devfreq/devfreq.c

diff --git a/Documentation/ABI/testing/sysfs-class-devfreq b/Documentation/ABI/testing/sysfs-class-devfreq
new file mode 100644 (file)
index 0000000..0ec855f
--- /dev/null
@@ -0,0 +1,44 @@
+What:          /sys/class/devfreq/.../
+Date:          September 2011
+Contact:       MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+               Provide a place in sysfs for the devfreq objects.
+               This allows accessing various devfreq specific variables.
+               The name of devfreq object denoted as ... is same as the
+               name of device using devfreq.
+
+What:          /sys/class/devfreq/.../governor
+Date:          September 2011
+Contact:       MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+               The /sys/class/devfreq/.../governor shows the name of the
+               governor used by the corresponding devfreq object.
+
+What:          /sys/class/devfreq/.../cur_freq
+Date:          September 2011
+Contact:       MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+               The /sys/class/devfreq/.../cur_freq shows the current
+               frequency of the corresponding devfreq object.
+
+What:          /sys/class/devfreq/.../central_polling
+Date:          September 2011
+Contact:       MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+               The /sys/class/devfreq/.../central_polling shows whether
+               the devfreq ojbect is using devfreq-provided central
+               polling mechanism or not.
+
+What:          /sys/class/devfreq/.../polling_interval
+Date:          September 2011
+Contact:       MyungJoo Ham <myungjoo.ham@samsung.com>
+Description:
+               The /sys/class/devfreq/.../polling_interval shows and sets
+               the requested polling interval of the corresponding devfreq
+               object. The values are represented in ms. If the value is
+               less than 1 jiffy, it is considered to be 0, which means
+               no polling. This value is meaningless if the governor is
+               not polling; thus. If the governor is not using
+               devfreq-provided central polling
+               (/sys/class/devfreq/.../central_polling is 0), this value
+               may be useless.
index f3100b1..5d15b81 100644 (file)
@@ -437,6 +437,74 @@ int devfreq_remove_device(struct devfreq *devfreq)
        return 0;
 }
 
+static ssize_t show_governor(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
+}
+
+static ssize_t show_freq(struct device *dev,
+                        struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%lu\n", to_devfreq(dev)->previous_freq);
+}
+
+static ssize_t show_polling_interval(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", to_devfreq(dev)->profile->polling_ms);
+}
+
+static ssize_t store_polling_interval(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count)
+{
+       struct devfreq *df = to_devfreq(dev);
+       unsigned int value;
+       int ret;
+
+       ret = sscanf(buf, "%u", &value);
+       if (ret != 1)
+               goto out;
+
+       mutex_lock(&df->lock);
+       df->profile->polling_ms = value;
+       df->next_polling = df->polling_jiffies
+                        = msecs_to_jiffies(value);
+       mutex_unlock(&df->lock);
+
+       ret = count;
+
+       if (df->governor->no_central_polling)
+               goto out;
+
+       mutex_lock(&devfreq_list_lock);
+       if (df->next_polling > 0 && !polling) {
+               polling = true;
+               queue_delayed_work(devfreq_wq, &devfreq_work,
+                                  df->next_polling);
+       }
+       mutex_unlock(&devfreq_list_lock);
+out:
+       return ret;
+}
+
+static ssize_t show_central_polling(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n",
+                      !to_devfreq(dev)->governor->no_central_polling);
+}
+
+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),
+       { },
+};
+
 /**
  * devfreq_start_polling() - Initialize data structure for devfreq framework and
  *                        start polling registered devfreq devices.
@@ -461,6 +529,7 @@ static int __init devfreq_init(void)
                pr_err("%s: couldn't create class\n", __FILE__);
                return PTR_ERR(devfreq_class);
        }
+       devfreq_class->dev_attrs = devfreq_attrs;
        return 0;
 }
 subsys_initcall(devfreq_init);