Subversion Repositories shark

Rev

Rev 770 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
582 mauro 1
/*
2
 * linux/drivers/cpufreq/freq_table.c
3
 *
4
 * Copyright (C) 2002 - 2003 Dominik Brodowski
5
 */
6
 
7
#include <linux/kernel.h>
8
#include <linux/module.h>
9
#include <linux/init.h>
10
#include <linux/cpufreq.h>
11
 
12
/*********************************************************************
13
 *                     FREQUENCY TABLE HELPERS                       *
14
 *********************************************************************/
15
 
16
int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
17
                                    struct cpufreq_frequency_table *table)
18
{
19
        unsigned int min_freq = ~0;
20
        unsigned int max_freq = 0;
21
        unsigned int i = 0;
22
 
23
        for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
24
                unsigned int freq = table[i].frequency;
25
                if (freq == CPUFREQ_ENTRY_INVALID)
26
                        continue;
27
                if (freq < min_freq)
28
                        min_freq = freq;
29
                if (freq > max_freq)
30
                        max_freq = freq;
31
        }
32
 
33
        policy->min = policy->cpuinfo.min_freq = min_freq;
34
        policy->max = policy->cpuinfo.max_freq = max_freq;
35
 
36
        if (policy->min == ~0)
37
                return -EINVAL;
38
        else
39
                return 0;
40
}
41
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
42
 
43
 
44
int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
45
                                   struct cpufreq_frequency_table *table)
46
{
47
        unsigned int next_larger = ~0;
48
        unsigned int i = 0;
49
        unsigned int count = 0;
50
 
51
        if (!cpu_online(policy->cpu))
52
                return -EINVAL;
53
 
54
        cpufreq_verify_within_limits(policy,
55
                                     policy->cpuinfo.min_freq,
56
                                     policy->cpuinfo.max_freq);
57
 
58
        for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
59
                unsigned int freq = table[i].frequency;
60
                if (freq == CPUFREQ_ENTRY_INVALID)
61
                        continue;
62
                if ((freq >= policy->min) && (freq <= policy->max))
63
                        count++;
64
                else if ((next_larger > freq) && (freq > policy->max))
65
                        next_larger = freq;
66
        }
67
 
68
        if (!count)
69
                policy->max = next_larger;
70
 
71
        cpufreq_verify_within_limits(policy,
72
                                     policy->cpuinfo.min_freq,
73
                                     policy->cpuinfo.max_freq);
74
 
75
        return 0;
76
}
77
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
78
 
79
 
80
int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
81
                                   struct cpufreq_frequency_table *table,
82
                                   unsigned int target_freq,
83
                                   unsigned int relation,
84
                                   unsigned int *index)
85
{
86
        struct cpufreq_frequency_table optimal = { .index = ~0, };
87
        struct cpufreq_frequency_table suboptimal = { .index = ~0, };
88
        unsigned int i;
89
 
90
        switch (relation) {
91
        case CPUFREQ_RELATION_H:
92
                optimal.frequency = 0;
93
                suboptimal.frequency = ~0;
94
                break;
95
        case CPUFREQ_RELATION_L:
96
                optimal.frequency = ~0;
97
                suboptimal.frequency = 0;
98
                break;
99
        }
100
 
101
        if (!cpu_online(policy->cpu))
102
                return -EINVAL;
103
 
104
        for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
105
                unsigned int freq = table[i].frequency;
106
                if (freq == CPUFREQ_ENTRY_INVALID)
107
                        continue;
108
                if ((freq < policy->min) || (freq > policy->max))
109
                        continue;
110
                switch(relation) {
111
                case CPUFREQ_RELATION_H:
112
                        if (freq <= target_freq) {
113
                                if (freq >= optimal.frequency) {
114
                                        optimal.frequency = freq;
115
                                        optimal.index = i;
116
                                }
117
                        } else {
118
                                if (freq <= suboptimal.frequency) {
119
                                        suboptimal.frequency = freq;
120
                                        suboptimal.index = i;
121
                                }
122
                        }
123
                        break;
124
                case CPUFREQ_RELATION_L:
125
                        if (freq >= target_freq) {
126
                                if (freq <= optimal.frequency) {
127
                                        optimal.frequency = freq;
128
                                        optimal.index = i;
129
                                }
130
                        } else {
131
                                if (freq >= suboptimal.frequency) {
132
                                        suboptimal.frequency = freq;
133
                                        suboptimal.index = i;
134
                                }
135
                        }
136
                        break;
137
                }
138
        }
139
        if (optimal.index > i) {
140
                if (suboptimal.index > i)
141
                        return -EINVAL;
142
                *index = suboptimal.index;
143
        } else
144
                *index = optimal.index;
145
 
146
        return 0;
147
}
148
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
149
 
150
static struct cpufreq_frequency_table *show_table[NR_CPUS];
151
/**
152
 * show_scaling_governor - show the current policy for the specified CPU
153
 */
154
static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
155
{
156
        unsigned int i = 0;
157
        unsigned int cpu = policy->cpu;
158
        ssize_t count = 0;
159
        struct cpufreq_frequency_table *table;
160
 
161
        if (!show_table[cpu])
162
                return -ENODEV;
163
 
164
        table = show_table[cpu];
165
 
166
        for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
167
                if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
168
                        continue;
169
                count += sprintf26(&buf[count], "%d ", table[i].frequency);
170
        }
171
        count += sprintf26(&buf[count], "\n");
172
 
173
        return count;
174
 
175
}
176
 
177
struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
178
        .attr = { .name = "scaling_available_frequencies", .mode = 0444 },
179
        .show = show_available_freqs,
180
};
181
EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
182
 
183
/*
184
 * if you use these, you must assure that the frequency table is valid
185
 * all the time between get_attr and put_attr!
186
 */
187
void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
188
                                      unsigned int cpu)
189
{
190
        show_table[cpu] = table;
191
}
192
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);
193
 
194
void cpufreq_frequency_table_put_attr(unsigned int cpu)
195
{
196
        show_table[cpu] = NULL;
197
}
198
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
199
 
200
 
201
MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
202
MODULE_DESCRIPTION ("CPUfreq frequency table helpers");
203
MODULE_LICENSE ("GPL");