2 * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
4 * Licensed under the terms of the GNU GPL License version 2.
6 * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/slab.h>
13 #include <linux/cpufreq.h>
16 #include <asm/processor.h>
17 #include <asm/timex.h>
19 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longrun", msg)
21 static struct cpufreq_driver longrun_driver
;
24 * longrun_{low,high}_freq is needed for the conversion of cpufreq kHz
25 * values into per cent values. In TMTA microcode, the following is valid:
26 * performance_pctg = (current_freq - low_freq)/(high_freq - low_freq)
28 static unsigned int longrun_low_freq
, longrun_high_freq
;
32 * longrun_get_policy - get the current LongRun policy
33 * @policy: struct cpufreq_policy where current policy is written into
35 * Reads the current LongRun policy by access to MSR_TMTA_LONGRUN_FLAGS
36 * and MSR_TMTA_LONGRUN_CTRL
38 static void __init
longrun_get_policy(struct cpufreq_policy
*policy
)
42 rdmsr(MSR_TMTA_LONGRUN_FLAGS
, msr_lo
, msr_hi
);
43 dprintk("longrun flags are %x - %x\n", msr_lo
, msr_hi
);
45 policy
->policy
= CPUFREQ_POLICY_PERFORMANCE
;
47 policy
->policy
= CPUFREQ_POLICY_POWERSAVE
;
49 rdmsr(MSR_TMTA_LONGRUN_CTRL
, msr_lo
, msr_hi
);
50 dprintk("longrun ctrl is %x - %x\n", msr_lo
, msr_hi
);
54 if ( longrun_high_freq
<= longrun_low_freq
) {
55 /* Assume degenerate Longrun table */
56 policy
->min
= policy
->max
= longrun_high_freq
;
58 policy
->min
= longrun_low_freq
+ msr_lo
*
59 ((longrun_high_freq
- longrun_low_freq
) / 100);
60 policy
->max
= longrun_low_freq
+ msr_hi
*
61 ((longrun_high_freq
- longrun_low_freq
) / 100);
68 * longrun_set_policy - sets a new CPUFreq policy
71 * Sets a new CPUFreq policy on LongRun-capable processors. This function
72 * has to be called with cpufreq_driver locked.
74 static int longrun_set_policy(struct cpufreq_policy
*policy
)
82 if ( longrun_high_freq
<= longrun_low_freq
) {
83 /* Assume degenerate Longrun table */
84 pctg_lo
= pctg_hi
= 100;
86 pctg_lo
= (policy
->min
- longrun_low_freq
) /
87 ((longrun_high_freq
- longrun_low_freq
) / 100);
88 pctg_hi
= (policy
->max
- longrun_low_freq
) /
89 ((longrun_high_freq
- longrun_low_freq
) / 100);
94 if (pctg_lo
> pctg_hi
)
97 /* performance or economy mode */
98 rdmsr(MSR_TMTA_LONGRUN_FLAGS
, msr_lo
, msr_hi
);
100 switch (policy
->policy
) {
101 case CPUFREQ_POLICY_PERFORMANCE
:
102 msr_lo
|= 0x00000001;
104 case CPUFREQ_POLICY_POWERSAVE
:
107 wrmsr(MSR_TMTA_LONGRUN_FLAGS
, msr_lo
, msr_hi
);
109 /* lower and upper boundary */
110 rdmsr(MSR_TMTA_LONGRUN_CTRL
, msr_lo
, msr_hi
);
111 msr_lo
&= 0xFFFFFF80;
112 msr_hi
&= 0xFFFFFF80;
115 wrmsr(MSR_TMTA_LONGRUN_CTRL
, msr_lo
, msr_hi
);
122 * longrun_verify_poliy - verifies a new CPUFreq policy
123 * @policy: the policy to verify
125 * Validates a new CPUFreq policy. This function has to be called with
126 * cpufreq_driver locked.
128 static int longrun_verify_policy(struct cpufreq_policy
*policy
)
134 cpufreq_verify_within_limits(policy
,
135 policy
->cpuinfo
.min_freq
,
136 policy
->cpuinfo
.max_freq
);
138 if ((policy
->policy
!= CPUFREQ_POLICY_POWERSAVE
) &&
139 (policy
->policy
!= CPUFREQ_POLICY_PERFORMANCE
))
145 static unsigned int longrun_get(unsigned int cpu
)
147 u32 eax
, ebx
, ecx
, edx
;
152 cpuid(0x80860007, &eax
, &ebx
, &ecx
, &edx
);
153 dprintk("cpuid eax is %u\n", eax
);
159 * longrun_determine_freqs - determines the lowest and highest possible core frequency
160 * @low_freq: an int to put the lowest frequency into
161 * @high_freq: an int to put the highest frequency into
163 * Determines the lowest and highest possible core frequencies on this CPU.
164 * This is necessary to calculate the performance percentage according to
166 * performance_pctg = (target_freq - low_freq)/(high_freq - low_freq)
168 static unsigned int __init
longrun_determine_freqs(unsigned int *low_freq
,
169 unsigned int *high_freq
)
172 u32 save_lo
, save_hi
;
173 u32 eax
, ebx
, ecx
, edx
;
175 struct cpuinfo_x86
*c
= &cpu_data(0);
177 if (!low_freq
|| !high_freq
)
180 if (cpu_has(c
, X86_FEATURE_LRTI
)) {
181 /* if the LongRun Table Interface is present, the
182 * detection is a bit easier:
183 * For minimum frequency, read out the maximum
184 * level (msr_hi), write that into "currently
185 * selected level", and read out the frequency.
186 * For maximum frequency, read out level zero.
189 rdmsr(MSR_TMTA_LRTI_READOUT
, msr_lo
, msr_hi
);
190 wrmsr(MSR_TMTA_LRTI_READOUT
, msr_hi
, msr_hi
);
191 rdmsr(MSR_TMTA_LRTI_VOLT_MHZ
, msr_lo
, msr_hi
);
192 *low_freq
= msr_lo
* 1000; /* to kHz */
195 wrmsr(MSR_TMTA_LRTI_READOUT
, 0, msr_hi
);
196 rdmsr(MSR_TMTA_LRTI_VOLT_MHZ
, msr_lo
, msr_hi
);
197 *high_freq
= msr_lo
* 1000; /* to kHz */
199 dprintk("longrun table interface told %u - %u kHz\n", *low_freq
, *high_freq
);
201 if (*low_freq
> *high_freq
)
202 *low_freq
= *high_freq
;
206 /* set the upper border to the value determined during TSC init */
207 *high_freq
= (cpu_khz
/ 1000);
208 *high_freq
= *high_freq
* 1000;
209 dprintk("high frequency is %u kHz\n", *high_freq
);
211 /* get current borders */
212 rdmsr(MSR_TMTA_LONGRUN_CTRL
, msr_lo
, msr_hi
);
213 save_lo
= msr_lo
& 0x0000007F;
214 save_hi
= msr_hi
& 0x0000007F;
216 /* if current perf_pctg is larger than 90%, we need to decrease the
217 * upper limit to make the calculation more accurate.
219 cpuid(0x80860007, &eax
, &ebx
, &ecx
, &edx
);
220 /* try decreasing in 10% steps, some processors react only
221 * on some barrier values */
222 for (try_hi
= 80; try_hi
> 0 && ecx
> 90; try_hi
-=10) {
223 /* set to 0 to try_hi perf_pctg */
224 msr_lo
&= 0xFFFFFF80;
225 msr_hi
&= 0xFFFFFF80;
227 wrmsr(MSR_TMTA_LONGRUN_CTRL
, msr_lo
, msr_hi
);
229 /* read out current core MHz and current perf_pctg */
230 cpuid(0x80860007, &eax
, &ebx
, &ecx
, &edx
);
233 wrmsr(MSR_TMTA_LONGRUN_CTRL
, save_lo
, save_hi
);
235 dprintk("percentage is %u %%, freq is %u MHz\n", ecx
, eax
);
237 /* performance_pctg = (current_freq - low_freq)/(high_freq - low_freq)
239 * low_freq * ( 1 - perf_pctg) = (cur_freq - high_freq * perf_pctg)
241 * high_freq * perf_pctg is stored tempoarily into "ebx".
243 ebx
= (((cpu_khz
/ 1000) * ecx
) / 100); /* to MHz */
245 if ((ecx
> 95) || (ecx
== 0) || (eax
< ebx
))
248 edx
= (eax
- ebx
) / (100 - ecx
);
249 *low_freq
= edx
* 1000; /* back to kHz */
251 dprintk("low frequency is %u kHz\n", *low_freq
);
253 if (*low_freq
> *high_freq
)
254 *low_freq
= *high_freq
;
260 static int __init
longrun_cpu_init(struct cpufreq_policy
*policy
)
264 /* capability check */
265 if (policy
->cpu
!= 0)
268 /* detect low and high frequency */
269 result
= longrun_determine_freqs(&longrun_low_freq
, &longrun_high_freq
);
273 /* cpuinfo and default policy values */
274 policy
->cpuinfo
.min_freq
= longrun_low_freq
;
275 policy
->cpuinfo
.max_freq
= longrun_high_freq
;
276 policy
->cpuinfo
.transition_latency
= CPUFREQ_ETERNAL
;
277 longrun_get_policy(policy
);
283 static struct cpufreq_driver longrun_driver
= {
284 .flags
= CPUFREQ_CONST_LOOPS
,
285 .verify
= longrun_verify_policy
,
286 .setpolicy
= longrun_set_policy
,
288 .init
= longrun_cpu_init
,
290 .owner
= THIS_MODULE
,
295 * longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver
297 * Initializes the LongRun support.
299 static int __init
longrun_init(void)
301 struct cpuinfo_x86
*c
= &cpu_data(0);
303 if (c
->x86_vendor
!= X86_VENDOR_TRANSMETA
||
304 !cpu_has(c
, X86_FEATURE_LONGRUN
))
307 return cpufreq_register_driver(&longrun_driver
);
312 * longrun_exit - unregisters LongRun support
314 static void __exit
longrun_exit(void)
316 cpufreq_unregister_driver(&longrun_driver
);
320 MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
321 MODULE_DESCRIPTION ("LongRun driver for Transmeta Crusoe and Efficeon processors.");
322 MODULE_LICENSE ("GPL");
324 module_init(longrun_init
);
325 module_exit(longrun_exit
);