Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
b04d73e8
Commit
b04d73e8
authored
Jun 25, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://linux-dj.bkbits.net/cpufreq
into home.osdl.org:/home/torvalds/v2.5/linux
parents
508e50ca
91151ea2
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
410 additions
and
465 deletions
+410
-465
Documentation/cpu-freq/user-guide.txt
Documentation/cpu-freq/user-guide.txt
+3
-7
arch/i386/kernel/cpu/cpufreq/Kconfig
arch/i386/kernel/cpu/cpufreq/Kconfig
+5
-0
arch/i386/kernel/cpu/cpufreq/Makefile
arch/i386/kernel/cpu/cpufreq/Makefile
+1
-0
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+1
-1
arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
+84
-457
arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
+275
-0
arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
+41
-0
No files found.
Documentation/cpu-freq/user-guide.txt
View file @
b04d73e8
...
...
@@ -56,19 +56,15 @@ AMD mobile K6-3+
AMD mobile Duron
AMD mobile Athlon
Cyrix Media GXm
Intel mobile PIII
[*]
and Intel mobile PIII-M on certain chipsets
Intel mobile PIII and Intel mobile PIII-M on certain chipsets
Intel Pentium 4, Intel Xeon
Intel Pentium M (Centrino)
National Semiconductors Geode GX
Transmeta Crusoe
VIA Cyrix 3 / C3
various processors on some ACPI 2.0-compatible systems [*
*
]
various processors on some ACPI 2.0-compatible systems [*]
[*] only certain Intel mobile PIII processors are supported. If you
know that you own a speedstep-capable processor, pass the option
"speedstep_coppermine=1" to the module speedstep.o
[**] Only if "ACPI Processor Performance States" are available
[*] Only if "ACPI Processor Performance States" are available
to the ACPI<->BIOS interface.
...
...
arch/i386/kernel/cpu/cpufreq/Kconfig
View file @
b04d73e8
...
...
@@ -123,6 +123,11 @@ config X86_SPEEDSTEP_CENTRINO
If in doubt, say N.
config X86_SPEEDSTEP_LIB
tristate
depends on X86_SPEEDSTEP_ICH
default X86_SPEEDSTEP_ICH
config X86_P4_CLOCKMOD
tristate "Intel Pentium 4 clock modulation"
depends on CPU_FREQ_TABLE
...
...
arch/i386/kernel/cpu/cpufreq/Makefile
View file @
b04d73e8
...
...
@@ -8,6 +8,7 @@ obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o
obj-$(CONFIG_X86_ACPI_CPUFREQ)
+=
acpi.o
obj-$(CONFIG_X86_SPEEDSTEP_ICH)
+=
speedstep-ich.o
obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO)
+=
speedstep-centrino.o
obj-$(CONFIG_X86_SPEEDSTEP_LIB)
+=
speedstep-lib.o
ifdef
CONFIG_X86_ACPI_CPUFREQ
ifdef
CONFIG_ACPI_DEBUG
...
...
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
View file @
b04d73e8
...
...
@@ -29,7 +29,7 @@
#define PFX "speedstep-centrino: "
#define MAINTAINER "Jeremy Fitzhardinge <jeremy@goop.org>"
#define CENTRINO_DEBUG
/*#define CENTRINO_DEBUG*/
#ifdef CENTRINO_DEBUG
#define dprintk(msg...) printk(msg)
...
...
arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
View file @
b04d73e8
/*
* $Id: speedstep.c,v 1.70 2003/02/22 10:23:46 db Exp $
*
* (C) 2001 Dave Jones, Arjan van de ven.
* (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
*
...
...
@@ -27,46 +25,32 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <asm/msr.h>
#include "speedstep-lib.h"
/* speedstep_chipset:
* It is necessary to know which chipset is used. As accesses to
* this device occur at various places in this module, we need a
* static struct pci_dev * pointing to that device.
*/
static
unsigned
int
speedstep_chipset
;
static
struct
pci_dev
*
speedstep_chipset_dev
;
#define SPEEDSTEP_CHIPSET_ICH2M 0x00000002
#define SPEEDSTEP_CHIPSET_ICH3M 0x00000003
#define SPEEDSTEP_CHIPSET_ICH4M 0x00000004
/* speedstep_processor
*/
static
unsigned
int
speedstep_processor
=
0
;
static
int
speedstep_coppermine
=
0
;
#define SPEEDSTEP_PROCESSOR_PIII_C 0x00000001
/* Coppermine core */
#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000002
/* Tualatin core */
#define SPEEDSTEP_PROCESSOR_P4M 0x00000003
/* P4-M with 100 MHz FSB */
/*
speedstep_[low,high]_freq
/*
* There are only two frequency states for each processor. Values
* are in kHz for the time being.
*/
#define SPEEDSTEP_HIGH 0x00000000
#define SPEEDSTEP_LOW 0x00000001
static
struct
cpufreq_frequency_table
speedstep_freqs
[]
=
{
{
SPEEDSTEP_HIGH
,
0
},
{
SPEEDSTEP_LOW
,
0
},
{
0
,
CPUFREQ_TABLE_END
},
};
#define speedstep_low_freq speedstep_freqs[SPEEDSTEP_LOW].frequency
#define speedstep_high_freq speedstep_freqs[SPEEDSTEP_HIGH].frequency
/* DEBUG
* Define it if you want verbose debug output, e.g. for bug reporting
...
...
@@ -80,93 +64,30 @@ static struct cpufreq_frequency_table speedstep_freqs[] = {
#endif
/*********************************************************************
* LOW LEVEL CHIPSET INTERFACE *
*********************************************************************/
/**
* speedstep_get_state - read the current SpeedStep state
* @state: Speedstep state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
*
* Tries to read the SpeedStep state. Returns -EIO when there has been
* trouble to read the status or write to the control register, -EINVAL
* on an unsupported chipset, and zero on success.
*/
static
int
speedstep_get_state
(
unsigned
int
*
state
)
{
unsigned
long
flags
;
u32
pmbase
;
u8
value
;
if
(
!
speedstep_chipset_dev
||
!
state
)
return
-
EINVAL
;
switch
(
speedstep_chipset
)
{
case
SPEEDSTEP_CHIPSET_ICH2M
:
case
SPEEDSTEP_CHIPSET_ICH3M
:
case
SPEEDSTEP_CHIPSET_ICH4M
:
/* get PMBASE */
pci_read_config_dword
(
speedstep_chipset_dev
,
0x40
,
&
pmbase
);
if
(
!
(
pmbase
&
0x01
))
return
-
EIO
;
pmbase
&=
0xFFFFFFFE
;
if
(
!
pmbase
)
return
-
EIO
;
/* read state */
local_irq_save
(
flags
);
value
=
inb
(
pmbase
+
0x50
);
local_irq_restore
(
flags
);
dprintk
(
KERN_DEBUG
"cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x
\n
"
,
pmbase
,
value
);
*
state
=
value
&
0x01
;
return
0
;
}
printk
(
KERN_ERR
"cpufreq: setting CPU frequency on this chipset unsupported.
\n
"
);
return
-
EINVAL
;
}
/**
* speedstep_set_state - set the SpeedStep state
* @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
*
* Tries to change the SpeedStep state.
*/
static
void
speedstep_set_state
(
unsigned
int
state
,
int
notify
)
static
void
speedstep_set_state
(
unsigned
int
state
,
unsigned
int
notify
)
{
u32
pmbase
;
u8
pm2_blk
;
u8
value
;
unsigned
long
flags
;
unsigned
int
oldstate
;
struct
cpufreq_freqs
freqs
;
if
(
!
speedstep_chipset_dev
||
(
state
>
0x1
))
return
;
if
(
speedstep_get_state
(
&
oldstate
))
return
;
if
(
oldstate
==
state
)
return
;
freqs
.
old
=
(
oldstate
==
SPEEDSTEP_HIGH
)
?
speedstep_high_freq
:
speedstep_low_freq
;
freqs
.
new
=
(
state
==
SPEEDSTEP_HIGH
)
?
speedstep_high_freq
:
speedstep_low_freq
;
freqs
.
old
=
speedstep_get_processor_frequency
(
speedstep_processor
);
freqs
.
new
=
speedstep_freqs
[
SPEEDSTEP_LOW
].
frequency
;
freqs
.
cpu
=
0
;
/* speedstep.c is UP only driver */
if
(
notify
)
cpufreq_notify_transition
(
&
freqs
,
CPUFREQ_PRECHANGE
);
switch
(
speedstep_chipset
)
{
case
SPEEDSTEP_CHIPSET_ICH2M
:
case
SPEEDSTEP_CHIPSET_ICH3M
:
case
SPEEDSTEP_CHIPSET_ICH4M
:
/* get PMBASE */
pci_read_config_dword
(
speedstep_chipset_dev
,
0x40
,
&
pmbase
);
if
(
!
(
pmbase
&
0x01
))
...
...
@@ -220,10 +141,6 @@ static void speedstep_set_state (unsigned int state, int notify)
}
else
{
printk
(
KERN_ERR
"cpufreq: change failed - I/O error
\n
"
);
}
break
;
default:
printk
(
KERN_ERR
"cpufreq: setting CPU frequency on this chipset unsupported.
\n
"
);
}
if
(
notify
)
cpufreq_notify_transition
(
&
freqs
,
CPUFREQ_POSTCHANGE
);
...
...
@@ -240,16 +157,11 @@ static void speedstep_set_state (unsigned int state, int notify)
*/
static
int
speedstep_activate
(
void
)
{
u16
value
=
0
;
if
(
!
speedstep_chipset_dev
)
return
-
EINVAL
;
switch
(
speedstep_chipset
)
{
case
SPEEDSTEP_CHIPSET_ICH2M
:
case
SPEEDSTEP_CHIPSET_ICH3M
:
case
SPEEDSTEP_CHIPSET_ICH4M
:
{
u16
value
=
0
;
pci_read_config_word
(
speedstep_chipset_dev
,
0x00A0
,
&
value
);
if
(
!
(
value
&
0x08
))
{
...
...
@@ -260,11 +172,6 @@ static int speedstep_activate (void)
}
return
0
;
}
}
printk
(
KERN_ERR
"cpufreq: SpeedStep (TM) on this chipset unsupported.
\n
"
);
return
-
EINVAL
;
}
...
...
@@ -284,7 +191,7 @@ static unsigned int speedstep_detect_chipset (void)
PCI_ANY_ID
,
NULL
);
if
(
speedstep_chipset_dev
)
return
SPEEDSTEP_CHIPSET_ICH4M
;
return
4
;
/* 4-M */
speedstep_chipset_dev
=
pci_find_subsys
(
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_82801CA_12
,
...
...
@@ -292,7 +199,7 @@ static unsigned int speedstep_detect_chipset (void)
PCI_ANY_ID
,
NULL
);
if
(
speedstep_chipset_dev
)
return
SPEEDSTEP_CHIPSET_ICH3M
;
return
3
;
/* 3-M */
speedstep_chipset_dev
=
pci_find_subsys
(
PCI_VENDOR_ID_INTEL
,
...
...
@@ -315,7 +222,7 @@ static unsigned int speedstep_detect_chipset (void)
NULL
);
if
(
!
hostbridge
)
return
SPEEDSTEP_CHIPSET_ICH2M
;
return
2
;
/* 2-M */
pci_read_config_byte
(
hostbridge
,
PCI_REVISION_ID
,
&
rev
);
if
(
rev
<
5
)
{
...
...
@@ -324,270 +231,13 @@ static unsigned int speedstep_detect_chipset (void)
return
0
;
}
return
SPEEDSTEP_CHIPSET_ICH2M
;
return
2
;
/* 2-M */
}
return
0
;
}
/*********************************************************************
* LOW LEVEL PROCESSOR INTERFACE *
*********************************************************************/
/**
* pentium3_get_frequency - get the core frequencies for PIIIs
*
* Returns the core frequency of a Pentium III processor (in kHz)
*/
static
unsigned
int
pentium3_get_frequency
(
void
)
{
/* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */
struct
{
unsigned
int
ratio
;
/* Frequency Multiplier (x10) */
u8
bitmap
;
/* power on configuration bits
[27, 25:22] (in MSR 0x2a) */
}
msr_decode_mult
[]
=
{
{
30
,
0x01
},
{
35
,
0x05
},
{
40
,
0x02
},
{
45
,
0x06
},
{
50
,
0x00
},
{
55
,
0x04
},
{
60
,
0x0b
},
{
65
,
0x0f
},
{
70
,
0x09
},
{
75
,
0x0d
},
{
80
,
0x0a
},
{
85
,
0x26
},
{
90
,
0x20
},
{
100
,
0x2b
},
{
0
,
0xff
}
/* error or unknown value */
};
/* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */
struct
{
unsigned
int
value
;
/* Front Side Bus speed in MHz */
u8
bitmap
;
/* power on configuration bits [18: 19]
(in MSR 0x2a) */
}
msr_decode_fsb
[]
=
{
{
66
,
0x0
},
{
100
,
0x2
},
{
133
,
0x1
},
{
0
,
0xff
}
};
u32
msr_lo
,
msr_tmp
;
int
i
=
0
,
j
=
0
;
struct
cpuinfo_x86
*
c
=
cpu_data
;
/* read MSR 0x2a - we only need the low 32 bits */
rdmsr
(
MSR_IA32_EBL_CR_POWERON
,
msr_lo
,
msr_tmp
);
dprintk
(
KERN_DEBUG
"cpufreq: P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x
\n
"
,
msr_lo
,
msr_tmp
);
msr_tmp
=
msr_lo
;
/* decode the FSB */
msr_tmp
&=
0x00c0000
;
msr_tmp
>>=
18
;
while
(
msr_tmp
!=
msr_decode_fsb
[
i
].
bitmap
)
{
if
(
msr_decode_fsb
[
i
].
bitmap
==
0xff
)
return
-
EINVAL
;
i
++
;
}
/* decode the multiplier */
if
((
c
->
x86_model
==
0x08
)
&&
(
c
->
x86_mask
==
0x01
))
/* different on early Coppermine PIII */
msr_lo
&=
0x03c00000
;
else
msr_lo
&=
0x0bc00000
;
msr_lo
>>=
22
;
while
(
msr_lo
!=
msr_decode_mult
[
j
].
bitmap
)
{
if
(
msr_decode_mult
[
j
].
bitmap
==
0xff
)
return
-
EINVAL
;
j
++
;
}
return
(
msr_decode_mult
[
j
].
ratio
*
msr_decode_fsb
[
i
].
value
*
100
);
}
/**
* pentium4_get_frequency - get the core frequency for P4-Ms
*
* Should return the core frequency (in kHz) for P4-Ms.
*/
static
unsigned
int
pentium4_get_frequency
(
void
)
{
u32
msr_lo
,
msr_hi
;
rdmsr
(
0x2c
,
msr_lo
,
msr_hi
);
dprintk
(
KERN_DEBUG
"cpufreq: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x
\n
"
,
msr_lo
,
msr_hi
);
/* First 12 bits seem to change a lot (0x511, 0x410 and 0x30f seen
* yet). Next 12 bits always seem to be 0x300. If this is not true
* on this CPU, complain. Last 8 bits are frequency (in 100MHz).
*/
if
(
msr_hi
||
((
msr_lo
&
0x00FFF000
)
!=
0x300000
))
{
printk
(
KERN_DEBUG
"cpufreq: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x
\n
"
,
msr_lo
,
msr_hi
);
printk
(
KERN_INFO
"cpufreq: problem in initialization. Please contact Dominik Brodowski
\n
"
);
printk
(
KERN_INFO
"cpufreq: <linux@brodo.de> and attach this dmesg. Thanks in advance
\n
"
);
return
0
;
}
msr_lo
>>=
24
;
return
(
msr_lo
*
100000
);
}
/**
* speedstep_detect_processor - detect Intel SpeedStep-capable processors.
*
* Returns the SPEEDSTEP_PROCESSOR_-number for the detected processor,
* or zero on failure.
*/
static
unsigned
int
speedstep_detect_processor
(
void
)
{
struct
cpuinfo_x86
*
c
=
cpu_data
;
u32
ebx
;
if
((
c
->
x86_vendor
!=
X86_VENDOR_INTEL
)
||
((
c
->
x86
!=
6
)
&&
(
c
->
x86
!=
0xF
)))
return
0
;
if
(
c
->
x86
==
0xF
)
{
/* Intel Pentium 4 Mobile P4-M */
if
(
c
->
x86_model
!=
2
)
return
0
;
if
((
c
->
x86_mask
!=
4
)
&&
(
c
->
x86_mask
!=
7
))
return
0
;
ebx
=
cpuid_ebx
(
0x00000001
);
ebx
&=
0x000000FF
;
if
((
ebx
!=
0x0e
)
&&
(
ebx
!=
0x0f
))
return
0
;
return
SPEEDSTEP_PROCESSOR_P4M
;
}
switch
(
c
->
x86_model
)
{
case
0x0B
:
/* Intel PIII [Tualatin] */
/* cpuid_ebx(1) is 0x04 for desktop PIII,
0x06 for mobile PIII-M */
ebx
=
cpuid_ebx
(
0x00000001
);
ebx
&=
0x000000FF
;
if
(
ebx
!=
0x06
)
return
0
;
/* So far all PIII-M processors support SpeedStep. See
* Intel's 24540633.pdf of August 2002
*/
return
SPEEDSTEP_PROCESSOR_PIII_T
;
case
0x08
:
/* Intel PIII [Coppermine] */
{
u32
msr_lo
,
msr_hi
;
/* all mobile PIII Coppermines have FSB 100 MHz
* ==> sort out a few desktop PIIIs. */
rdmsr
(
MSR_IA32_EBL_CR_POWERON
,
msr_lo
,
msr_hi
);
dprintk
(
KERN_DEBUG
"cpufreq: Coppermine: MSR_IA32_EBL_Cr_POWERON is 0x%x, 0x%x
\n
"
,
msr_lo
,
msr_hi
);
msr_lo
&=
0x00c0000
;
if
(
msr_lo
!=
0x0080000
)
return
0
;
if
(
speedstep_coppermine
)
return
SPEEDSTEP_PROCESSOR_PIII_C
;
/*
* If the processor is a mobile version,
* platform ID has bit 50 set
* it has SpeedStep technology if either
* bit 56 or 57 is set
*/
rdmsr
(
MSR_IA32_PLATFORM_ID
,
msr_lo
,
msr_hi
);
dprintk
(
KERN_DEBUG
"cpufreq: Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x
\n
"
,
msr_lo
,
msr_hi
);
if
((
msr_hi
&
(
1
<<
18
))
&&
(
msr_hi
&
(
3
<<
24
)))
return
SPEEDSTEP_PROCESSOR_PIII_C
;
printk
(
KERN_INFO
"cpufreq: in case this is a SpeedStep-capable Intel Pentium III Coppermine
\n
"
);
printk
(
KERN_INFO
"cpufreq: processor, please pass the boot option or module parameter
\n
"
);
printk
(
KERN_INFO
"cpufreq: `speedstep_coppermine=1` to the kernel. Thanks!
\n
"
);
return
0
;
}
default:
return
0
;
}
}
/*********************************************************************
* HIGH LEVEL FUNCTIONS *
*********************************************************************/
/**
* speedstep_detect_speeds - detects low and high CPU frequencies.
*
* Detects the low and high CPU frequencies in kHz. Returns 0 on
* success or -EINVAL / -EIO on problems.
*/
static
int
speedstep_detect_speeds
(
void
)
{
unsigned
long
flags
;
unsigned
int
state
;
int
i
,
result
;
/* Disable irqs for entire detection process */
local_irq_save
(
flags
);
for
(
i
=
0
;
i
<
2
;
i
++
)
{
/* read the current state */
result
=
speedstep_get_state
(
&
state
);
if
(
result
)
{
local_irq_restore
(
flags
);
return
result
;
}
/* save the correct value, and switch to other */
if
(
state
==
SPEEDSTEP_LOW
)
{
switch
(
speedstep_processor
)
{
case
SPEEDSTEP_PROCESSOR_PIII_C
:
case
SPEEDSTEP_PROCESSOR_PIII_T
:
speedstep_low_freq
=
pentium3_get_frequency
();
break
;
case
SPEEDSTEP_PROCESSOR_P4M
:
speedstep_low_freq
=
pentium4_get_frequency
();
}
speedstep_set_state
(
SPEEDSTEP_HIGH
,
0
);
}
else
{
switch
(
speedstep_processor
)
{
case
SPEEDSTEP_PROCESSOR_PIII_C
:
case
SPEEDSTEP_PROCESSOR_PIII_T
:
speedstep_high_freq
=
pentium3_get_frequency
();
break
;
case
SPEEDSTEP_PROCESSOR_P4M
:
speedstep_high_freq
=
pentium4_get_frequency
();
}
speedstep_set_state
(
SPEEDSTEP_LOW
,
0
);
}
}
local_irq_restore
(
flags
);
if
(
!
speedstep_low_freq
||
!
speedstep_high_freq
||
(
speedstep_low_freq
==
speedstep_high_freq
))
return
-
EIO
;
return
0
;
}
/**
* speedstep_setpolicy - set a new CPUFreq policy
* @policy: new policy
...
...
@@ -632,22 +282,24 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
return
-
ENODEV
;
/* detect low and high frequency */
result
=
speedstep_detect_speeds
();
result
=
speedstep_get_freqs
(
speedstep_processor
,
&
speedstep_freqs
[
SPEEDSTEP_LOW
].
frequency
,
&
speedstep_freqs
[
SPEEDSTEP_HIGH
].
frequency
,
&
speedstep_set_state
);
if
(
result
)
return
result
;
/* get current speed setting */
result
=
speedstep_get_state
(
&
speed
);
if
(
result
)
return
result
;
speed
=
speedstep_get_processor_frequency
(
speedstep_processor
);
if
(
!
speed
)
return
-
EIO
;
speed
=
(
speed
==
SPEEDSTEP_LOW
)
?
speedstep_low_freq
:
speedstep_high_freq
;
dprintk
(
KERN_INFO
"cpufreq: currently at %s speed setting - %i MHz
\n
"
,
(
speed
==
speedstep_low_freq
)
?
"low"
:
"high"
,
(
speed
/
1000
));
/* cpuinfo and default policy values */
policy
->
policy
=
(
speed
==
speedstep_
low_freq
)
?
policy
->
policy
=
(
speed
==
speedstep_
freqs
[
SPEEDSTEP_LOW
].
frequency
)
?
CPUFREQ_POLICY_POWERSAVE
:
CPUFREQ_POLICY_PERFORMANCE
;
policy
->
cpuinfo
.
transition_latency
=
CPUFREQ_ETERNAL
;
policy
->
cur
=
speed
;
...
...
@@ -656,26 +308,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
}
#ifndef MODULE
/**
* speedstep_setup speedstep command line parameter parsing
*
* speedstep command line parameter. Use:
* speedstep_coppermine=1
* if the CPU in your notebook is a SpeedStep-capable Intel
* Pentium III Coppermine. These processors cannot be detected
* automatically, as Intel continues to consider the detection
* algorithm as proprietary material.
*/
static
int
__init
speedstep_setup
(
char
*
str
)
{
speedstep_coppermine
=
simple_strtoul
(
str
,
&
str
,
0
);
return
1
;
}
__setup
(
"speedstep_coppermine="
,
speedstep_setup
);
#endif
static
struct
cpufreq_driver
speedstep_driver
=
{
.
name
=
"speedstep"
,
.
verify
=
speedstep_verify
,
...
...
@@ -694,20 +326,17 @@ static struct cpufreq_driver speedstep_driver = {
*/
static
int
__init
speedstep_init
(
void
)
{
/* detect chipset */
speedstep_chipset
=
speedstep_detect_chipset
();
/* detect chipset */
if
(
speedstep_chipset
)
/* detect processor */
speedstep_processor
=
speedstep_detect_processor
();
if
(
!
speedstep_processor
)
return
-
ENODEV
;
if
((
!
speedstep_chipset
)
||
(
!
speedstep_processor
))
{
printk
(
KERN_INFO
"cpufreq: Intel(R) SpeedStep(TM) for this %s not (yet) available.
\n
"
,
speedstep_chipset
?
"processor"
:
"chipset"
);
/* detect chipset */
if
(
!
speedstep_detect_chipset
())
{
printk
(
KERN_INFO
"cpufreq: Intel(R) SpeedStep(TM) for this chipset not (yet) available.
\n
"
);
return
-
ENODEV
;
}
dprintk
(
KERN_INFO
"cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.70 $
\n
"
);
/* activate speedstep support */
if
(
speedstep_activate
())
return
-
EINVAL
;
...
...
@@ -727,10 +356,8 @@ static void __exit speedstep_exit(void)
}
MODULE_PARM
(
speedstep_coppermine
,
"i"
);
MODULE_AUTHOR
(
"Dave Jones <davej@suse.de>, Dominik Brodowski <linux@brodo.de>"
);
MODULE_DESCRIPTION
(
"Speedstep driver for Intel mobile processors."
);
MODULE_DESCRIPTION
(
"Speedstep driver for Intel mobile processors
on chipsets with ICH-M southbridges
."
);
MODULE_LICENSE
(
"GPL"
);
module_init
(
speedstep_init
);
...
...
arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
0 → 100644
View file @
b04d73e8
/*
* (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
*
* Licensed under the terms of the GNU GPL License version 2.
*
* Library for common functions for Intel SpeedStep v.1 and v.2 support
*
* BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cpufreq.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <asm/msr.h>
#include "speedstep-lib.h"
/* DEBUG
* Define it if you want verbose debug output, e.g. for bug reporting
*/
//#define SPEEDSTEP_DEBUG
#ifdef SPEEDSTEP_DEBUG
#define dprintk(msg...) printk(msg)
#else
#define dprintk(msg...) do { } while(0)
#endif
/*********************************************************************
* GET PROCESSOR CORE SPEED IN KHZ *
*********************************************************************/
static
unsigned
int
pentium3_get_frequency
(
unsigned
int
processor
)
{
/* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */
struct
{
unsigned
int
ratio
;
/* Frequency Multiplier (x10) */
u8
bitmap
;
/* power on configuration bits
[27, 25:22] (in MSR 0x2a) */
}
msr_decode_mult
[]
=
{
{
30
,
0x01
},
{
35
,
0x05
},
{
40
,
0x02
},
{
45
,
0x06
},
{
50
,
0x00
},
{
55
,
0x04
},
{
60
,
0x0b
},
{
65
,
0x0f
},
{
70
,
0x09
},
{
75
,
0x0d
},
{
80
,
0x0a
},
{
85
,
0x26
},
{
90
,
0x20
},
{
100
,
0x2b
},
{
0
,
0xff
}
/* error or unknown value */
};
/* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */
struct
{
unsigned
int
value
;
/* Front Side Bus speed in MHz */
u8
bitmap
;
/* power on configuration bits [18: 19]
(in MSR 0x2a) */
}
msr_decode_fsb
[]
=
{
{
66
,
0x0
},
{
100
,
0x2
},
{
133
,
0x1
},
{
0
,
0xff
}
};
u32
msr_lo
,
msr_tmp
;
int
i
=
0
,
j
=
0
;
/* read MSR 0x2a - we only need the low 32 bits */
rdmsr
(
MSR_IA32_EBL_CR_POWERON
,
msr_lo
,
msr_tmp
);
dprintk
(
KERN_DEBUG
"speedstep-lib: P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x
\n
"
,
msr_lo
,
msr_tmp
);
msr_tmp
=
msr_lo
;
/* decode the FSB */
msr_tmp
&=
0x00c0000
;
msr_tmp
>>=
18
;
while
(
msr_tmp
!=
msr_decode_fsb
[
i
].
bitmap
)
{
if
(
msr_decode_fsb
[
i
].
bitmap
==
0xff
)
return
0
;
i
++
;
}
/* decode the multiplier */
if
(
processor
==
SPEEDSTEP_PROCESSOR_PIII_C_EARLY
)
msr_lo
&=
0x03c00000
;
else
msr_lo
&=
0x0bc00000
;
msr_lo
>>=
22
;
while
(
msr_lo
!=
msr_decode_mult
[
j
].
bitmap
)
{
if
(
msr_decode_mult
[
j
].
bitmap
==
0xff
)
return
0
;
j
++
;
}
return
(
msr_decode_mult
[
j
].
ratio
*
msr_decode_fsb
[
i
].
value
*
100
);
}
static
unsigned
int
pentium4_get_frequency
(
void
)
{
u32
msr_lo
,
msr_hi
;
rdmsr
(
0x2c
,
msr_lo
,
msr_hi
);
dprintk
(
KERN_DEBUG
"speedstep-lib: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x
\n
"
,
msr_lo
,
msr_hi
);
msr_lo
>>=
24
;
return
(
msr_lo
*
100000
);
}
unsigned
int
speedstep_get_processor_frequency
(
unsigned
int
processor
)
{
switch
(
processor
)
{
case
SPEEDSTEP_PROCESSOR_P4M
:
return
pentium4_get_frequency
();
case
SPEEDSTEP_PROCESSOR_PIII_T
:
case
SPEEDSTEP_PROCESSOR_PIII_C
:
case
SPEEDSTEP_PROCESSOR_PIII_C_EARLY
:
return
pentium3_get_frequency
(
processor
);
default:
return
0
;
};
return
0
;
}
EXPORT_SYMBOL_GPL
(
speedstep_get_processor_frequency
);
/*********************************************************************
* DETECT SPEEDSTEP-CAPABLE PROCESSOR *
*********************************************************************/
unsigned
int
speedstep_detect_processor
(
void
)
{
struct
cpuinfo_x86
*
c
=
cpu_data
;
u32
ebx
,
msr_lo
,
msr_hi
;
if
((
c
->
x86_vendor
!=
X86_VENDOR_INTEL
)
||
((
c
->
x86
!=
6
)
&&
(
c
->
x86
!=
0xF
)))
return
0
;
if
(
c
->
x86
==
0xF
)
{
/* Intel Mobile Pentium 4-M
* or Intel Mobile Pentium 4 with 533 MHz FSB */
if
(
c
->
x86_model
!=
2
)
return
0
;
if
((
c
->
x86_mask
!=
4
)
&&
/* B-stepping [M-P4-M] */
(
c
->
x86_mask
!=
7
)
&&
/* C-stepping [M-P4-M] */
(
c
->
x86_mask
!=
9
))
/* D-stepping [M-P4-M or M-P4/533] */
return
0
;
ebx
=
cpuid_ebx
(
0x00000001
);
ebx
&=
0x000000FF
;
if
((
ebx
!=
0x0e
)
&&
(
ebx
!=
0x0f
))
return
0
;
return
SPEEDSTEP_PROCESSOR_P4M
;
}
switch
(
c
->
x86_model
)
{
case
0x0B
:
/* Intel PIII [Tualatin] */
/* cpuid_ebx(1) is 0x04 for desktop PIII,
0x06 for mobile PIII-M */
ebx
=
cpuid_ebx
(
0x00000001
);
ebx
&=
0x000000FF
;
if
(
ebx
!=
0x06
)
return
0
;
/* So far all PIII-M processors support SpeedStep. See
* Intel's 24540640.pdf of June 2003
*/
return
SPEEDSTEP_PROCESSOR_PIII_T
;
case
0x08
:
/* Intel PIII [Coppermine] */
/* all mobile PIII Coppermines have FSB 100 MHz
* ==> sort out a few desktop PIIIs. */
rdmsr
(
MSR_IA32_EBL_CR_POWERON
,
msr_lo
,
msr_hi
);
dprintk
(
KERN_DEBUG
"cpufreq: Coppermine: MSR_IA32_EBL_CR_POWERON is 0x%x, 0x%x
\n
"
,
msr_lo
,
msr_hi
);
msr_lo
&=
0x00c0000
;
if
(
msr_lo
!=
0x0080000
)
return
0
;
/*
* If the processor is a mobile version,
* platform ID has bit 50 set
* it has SpeedStep technology if either
* bit 56 or 57 is set
*/
rdmsr
(
MSR_IA32_PLATFORM_ID
,
msr_lo
,
msr_hi
);
dprintk
(
KERN_DEBUG
"cpufreq: Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x
\n
"
,
msr_lo
,
msr_hi
);
if
((
msr_hi
&
(
1
<<
18
))
&&
(
msr_hi
&
(
3
<<
24
)))
{
if
(
c
->
x86_mask
==
0x01
)
return
SPEEDSTEP_PROCESSOR_PIII_C_EARLY
;
else
return
SPEEDSTEP_PROCESSOR_PIII_C
;
}
default:
return
0
;
}
}
EXPORT_SYMBOL_GPL
(
speedstep_detect_processor
);
/*********************************************************************
* DETECT SPEEDSTEP SPEEDS *
*********************************************************************/
unsigned
int
speedstep_get_freqs
(
unsigned
int
processor
,
unsigned
int
*
low_speed
,
unsigned
int
*
high_speed
,
void
(
*
set_state
)
(
unsigned
int
state
,
unsigned
int
notify
)
)
{
unsigned
int
prev_speed
;
unsigned
int
ret
=
0
;
unsigned
long
flags
;
if
((
!
processor
)
||
(
!
low_speed
)
||
(
!
high_speed
)
||
(
!
set_state
))
return
EINVAL
;
/* get current speed */
prev_speed
=
speedstep_get_processor_frequency
(
processor
);
if
(
!
prev_speed
)
return
EIO
;
local_irq_save
(
flags
);
/* switch to low state */
set_state
(
SPEEDSTEP_LOW
,
0
);
*
low_speed
=
speedstep_get_processor_frequency
(
processor
);
if
(
!*
low_speed
)
{
ret
=
EIO
;
goto
out
;
}
/* switch to high state */
set_state
(
SPEEDSTEP_HIGH
,
0
);
*
high_speed
=
speedstep_get_processor_frequency
(
processor
);
if
(
!*
high_speed
)
{
ret
=
EIO
;
goto
out
;
}
if
(
*
low_speed
==
*
high_speed
)
{
ret
=
ENODEV
;
goto
out
;
}
/* switch to previous state, if necessary */
if
(
*
high_speed
!=
prev_speed
)
set_state
(
SPEEDSTEP_LOW
,
0
);
out:
local_irq_restore
(
flags
);
return
(
ret
);
}
EXPORT_SYMBOL_GPL
(
speedstep_get_freqs
);
MODULE_AUTHOR
(
"Dominik Brodowski <linux@brodo.de>"
);
MODULE_DESCRIPTION
(
"Library for Intel SpeedStep 1 or 2 cpufreq drivers."
);
MODULE_LICENSE
(
"GPL"
);
arch/i386/kernel/cpu/cpufreq/speedstep-lib.h
0 → 100644
View file @
b04d73e8
/*
* (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de>
*
* Licensed under the terms of the GNU GPL License version 2.
*
* Library for common functions for Intel SpeedStep v.1 and v.2 support
*
* BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
*/
/* processors */
#define SPEEDSTEP_PROCESSOR_PIII_C_EARLY 0x00000001
/* Coppermine core */
#define SPEEDSTEP_PROCESSOR_PIII_C 0x00000002
/* Coppermine core */
#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000003
/* Tualatin core */
#define SPEEDSTEP_PROCESSOR_P4M 0x00000004
/* P4-M with 100 MHz FSB */
/* speedstep states -- only two of them */
#define SPEEDSTEP_HIGH 0x00000000
#define SPEEDSTEP_LOW 0x00000001
/* detect a speedstep-capable processor */
extern
unsigned
int
speedstep_detect_processor
(
void
);
/* detect the current speed (in khz) of the processor */
extern
unsigned
int
speedstep_get_processor_frequency
(
unsigned
int
processor
);
/* detect the low and high speeds of the processor. The callback
* set_state"'s first argument is either SPEEDSTEP_HIGH or
* SPEEDSTEP_LOW; the second argument is zero so that no
* cpufreq_notify_transition calls are initiated.
*/
extern
unsigned
int
speedstep_get_freqs
(
unsigned
int
processor
,
unsigned
int
*
low_speed
,
unsigned
int
*
high_speed
,
void
(
*
set_state
)
(
unsigned
int
state
,
unsigned
int
notify
));
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment