summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDominik Brodowski <linux@brodo.de>2003-02-14 20:44:13 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2003-02-14 20:44:13 -0800
commit589e8be90ac9053d12eff741aed5430edf062298 (patch)
tree0488bce01e62a65a0e1a5e2da93912dba28b0122 /drivers
parent4e075e505c8abcbc1ceb16f5fad01900751fe389 (diff)
[PATCH] cpufreq: move frequency table helpers to extra module
The CPU frequency table helpers can easily be modularized -- especially as they are not needed on all architectures, or for all drivers (even on x86 -- see longrun and gx-suspmod)
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/cpufreq/Makefile2
-rw-r--r--drivers/cpufreq/freq_table.c203
3 files changed, 206 insertions, 0 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 24a5350f7d53..458e82e75568 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -45,3 +45,4 @@ obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
obj-$(CONFIG_ISDN_BOOL) += isdn/
obj-$(CONFIG_MCA) += mca/
obj-$(CONFIG_EISA) += eisa/
+obj-$(CONFIG_CPU_FREQ) += cpufreq/
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
new file mode 100644
index 000000000000..6be9f5e6998c
--- /dev/null
+++ b/drivers/cpufreq/Makefile
@@ -0,0 +1,2 @@
+#CPUfreq governors and cross-arch helpers
+obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
new file mode 100644
index 000000000000..8922d0d4a363
--- /dev/null
+++ b/drivers/cpufreq/freq_table.c
@@ -0,0 +1,203 @@
+/*
+ * linux/drivers/cpufreq/freq_table.c
+ *
+ * Copyright (C) 2002 - 2003 Dominik Brodowski
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+
+/*********************************************************************
+ * FREQUENCY TABLE HELPERS *
+ *********************************************************************/
+
+int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
+ struct cpufreq_frequency_table *table)
+{
+ unsigned int min_freq = ~0;
+ unsigned int max_freq = 0;
+ unsigned int i = 0;
+
+ for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+ unsigned int freq = table[i].frequency;
+ if (freq == CPUFREQ_ENTRY_INVALID)
+ continue;
+ if (freq < min_freq)
+ min_freq = freq;
+ if (freq > max_freq)
+ max_freq = freq;
+ }
+
+ policy->min = policy->cpuinfo.min_freq = min_freq;
+ policy->max = policy->cpuinfo.max_freq = max_freq;
+
+ if (policy->min == ~0)
+ return -EINVAL;
+ else
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
+
+
+int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
+ struct cpufreq_frequency_table *table)
+{
+ unsigned int next_larger = ~0;
+ unsigned int i = 0;
+ unsigned int count = 0;
+
+ if (!cpu_online(policy->cpu))
+ return -EINVAL;
+
+ cpufreq_verify_within_limits(policy,
+ policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
+
+ for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+ unsigned int freq = table[i].frequency;
+ if (freq == CPUFREQ_ENTRY_INVALID)
+ continue;
+ if ((freq >= policy->min) && (freq <= policy->max))
+ count++;
+ else if ((next_larger > freq) && (freq > policy->max))
+ next_larger = freq;
+ }
+
+ if (!count)
+ policy->max = next_larger;
+
+ cpufreq_verify_within_limits(policy,
+ policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
+
+
+int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
+ struct cpufreq_frequency_table *table,
+ unsigned int *index)
+{
+ struct cpufreq_frequency_table optimal = { .index = ~0, };
+ unsigned int i;
+
+ switch (policy->policy) {
+ case CPUFREQ_POLICY_PERFORMANCE:
+ optimal.frequency = 0;
+ break;
+ case CPUFREQ_POLICY_POWERSAVE:
+ optimal.frequency = ~0;
+ break;
+ }
+
+ if (!cpu_online(policy->cpu))
+ return -EINVAL;
+
+ for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+ unsigned int freq = table[i].frequency;
+ if (freq == CPUFREQ_ENTRY_INVALID)
+ continue;
+ if ((freq < policy->min) || (freq > policy->max))
+ continue;
+ switch(policy->policy) {
+ case CPUFREQ_POLICY_PERFORMANCE:
+ if (optimal.frequency <= freq) {
+ optimal.frequency = freq;
+ optimal.index = i;
+ }
+ break;
+ case CPUFREQ_POLICY_POWERSAVE:
+ if (optimal.frequency >= freq) {
+ optimal.frequency = freq;
+ optimal.index = i;
+ }
+ break;
+ }
+ }
+ if (optimal.index > i)
+ return -EINVAL;
+
+ *index = optimal.index;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy);
+
+
+int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
+ struct cpufreq_frequency_table *table,
+ unsigned int target_freq,
+ unsigned int relation,
+ unsigned int *index)
+{
+ struct cpufreq_frequency_table optimal = { .index = ~0, };
+ struct cpufreq_frequency_table suboptimal = { .index = ~0, };
+ unsigned int i;
+
+ switch (relation) {
+ case CPUFREQ_RELATION_H:
+ optimal.frequency = 0;
+ suboptimal.frequency = ~0;
+ break;
+ case CPUFREQ_RELATION_L:
+ optimal.frequency = ~0;
+ suboptimal.frequency = 0;
+ break;
+ }
+
+ if (!cpu_online(policy->cpu))
+ return -EINVAL;
+
+ for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+ unsigned int freq = table[i].frequency;
+ if (freq == CPUFREQ_ENTRY_INVALID)
+ continue;
+ if ((freq < policy->min) || (freq > policy->max))
+ continue;
+ switch(relation) {
+ case CPUFREQ_RELATION_H:
+ if (freq <= target_freq) {
+ if (freq >= optimal.frequency) {
+ optimal.frequency = freq;
+ optimal.index = i;
+ }
+ } else {
+ if (freq <= suboptimal.frequency) {
+ suboptimal.frequency = freq;
+ suboptimal.index = i;
+ }
+ }
+ break;
+ case CPUFREQ_RELATION_L:
+ if (freq >= target_freq) {
+ if (freq <= optimal.frequency) {
+ optimal.frequency = freq;
+ optimal.index = i;
+ }
+ } else {
+ if (freq >= suboptimal.frequency) {
+ suboptimal.frequency = freq;
+ suboptimal.index = i;
+ }
+ }
+ break;
+ }
+ }
+ if (optimal.index > i) {
+ if (suboptimal.index > i)
+ return -EINVAL;
+ *index = suboptimal.index;
+ } else
+ *index = optimal.index;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
+
+
+MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
+MODULE_DESCRIPTION ("CPUfreq frequency table helpers");
+MODULE_LICENSE ("GPL");