diff options
| author | Nishanth Menon <nm@ti.com> | 2012-10-25 20:48:59 -0400 |
|---|---|---|
| committer | MyungJoo Ham <myungjoo.ham@samsung.com> | 2012-11-20 01:59:32 -0500 |
| commit | d287de855f97c56ca7146ff627e652bd7cd64f3f (patch) | |
| tree | a3dbeb4937853cf1e81dca65c97c2dbbda549129 /drivers/devfreq | |
| parent | e09651fcc295a7dc802f38d9494f5b860dd90bca (diff) | |
PM / devfreq: Add sysfs node to expose available frequencies
devfreq governors such as ondemand are controlled by a min and
max frequency, while governors like userspace governor allow us
to set a specific frequency.
However, for the same specific device, depending on the SoC, the
available frequencies can vary.
So expose the available frequencies as a snapshot over sysfs to
allow informed decisions.
This was inspired by cpufreq framework's equivalent for similar
usage sysfs node: scaling_available_frequencies.
Cc: Rajagopal Venkat <rajagopal.venkat@linaro.org>
Cc: MyungJoo Ham <myungjoo.ham@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Kevin Hilman <khilman@ti.com>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Diffstat (limited to 'drivers/devfreq')
| -rw-r--r-- | drivers/devfreq/devfreq.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 789af4ff5c9c..c44e562bdfe0 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c | |||
| @@ -570,9 +570,41 @@ static ssize_t show_max_freq(struct device *dev, struct device_attribute *attr, | |||
| 570 | return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq); | 570 | return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq); |
| 571 | } | 571 | } |
| 572 | 572 | ||
| 573 | static ssize_t show_available_freqs(struct device *d, | ||
| 574 | struct device_attribute *attr, | ||
| 575 | char *buf) | ||
| 576 | { | ||
| 577 | struct devfreq *df = to_devfreq(d); | ||
| 578 | struct device *dev = df->dev.parent; | ||
| 579 | struct opp *opp; | ||
| 580 | ssize_t count = 0; | ||
| 581 | unsigned long freq = 0; | ||
| 582 | |||
| 583 | rcu_read_lock(); | ||
| 584 | do { | ||
| 585 | opp = opp_find_freq_ceil(dev, &freq); | ||
| 586 | if (IS_ERR(opp)) | ||
| 587 | break; | ||
| 588 | |||
| 589 | count += scnprintf(&buf[count], (PAGE_SIZE - count - 2), | ||
| 590 | "%lu ", freq); | ||
| 591 | freq++; | ||
| 592 | } while (1); | ||
| 593 | rcu_read_unlock(); | ||
| 594 | |||
| 595 | /* Truncate the trailing space */ | ||
| 596 | if (count) | ||
| 597 | count--; | ||
| 598 | |||
| 599 | count += sprintf(&buf[count], "\n"); | ||
| 600 | |||
| 601 | return count; | ||
| 602 | } | ||
| 603 | |||
| 573 | static struct device_attribute devfreq_attrs[] = { | 604 | static struct device_attribute devfreq_attrs[] = { |
| 574 | __ATTR(governor, S_IRUGO, show_governor, NULL), | 605 | __ATTR(governor, S_IRUGO, show_governor, NULL), |
| 575 | __ATTR(cur_freq, S_IRUGO, show_freq, NULL), | 606 | __ATTR(cur_freq, S_IRUGO, show_freq, NULL), |
| 607 | __ATTR(available_frequencies, S_IRUGO, show_available_freqs, NULL), | ||
| 576 | __ATTR(target_freq, S_IRUGO, show_target_freq, NULL), | 608 | __ATTR(target_freq, S_IRUGO, show_target_freq, NULL), |
| 577 | __ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval, | 609 | __ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval, |
| 578 | store_polling_interval), | 610 | store_polling_interval), |
