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
nexedi
linux
Commits
33ab1d91
Commit
33ab1d91
authored
Feb 09, 2004
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
7b080b4c
0211af97
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
242 additions
and
362 deletions
+242
-362
arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
+44
-45
arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
+1
-1
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+3
-8
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+139
-294
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+0
-4
arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
+46
-8
drivers/cpufreq/cpufreq_userspace.c
drivers/cpufreq/cpufreq_userspace.c
+9
-2
No files found.
arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
View file @
33ab1d91
...
@@ -28,30 +28,34 @@
...
@@ -28,30 +28,34 @@
* with 'Suspend Modulation OFF Count Register'
* with 'Suspend Modulation OFF Count Register'
* and 'Suspend Modulation ON Count Register'.
* and 'Suspend Modulation ON Count Register'.
* These registers are 8bit counters that represent the number of
* These registers are 8bit counters that represent the number of
* 32us intervals which the SUSP# pin is asserted
/de-asserted to the
* 32us intervals which the SUSP# pin is asserted
(ON)/de-asserted(OFF)
* processor.
*
to the
processor.
*
*
* These counters define a ratio which is the effective frequency
* These counters define a ratio which is the effective frequency
* of operation of the system.
* of operation of the system.
*
*
* O
n
Count
* O
FF
Count
* F_eff = Fgx * ----------------------
* F_eff = Fgx * ----------------------
* O
n Count + Off
Count
* O
FF Count + ON
Count
*
*
* 0 <= On Count, Off Count <= 255
* 0 <= On Count, Off Count <= 255
*
*
* From these limits, we can get register values
* From these limits, we can get register values
*
*
* o
n_duration + off
_duration <= MAX_DURATION
* o
ff_duration + on
_duration <= MAX_DURATION
* o
ff_duration = on
_duration * (stock_freq - freq) / freq
* o
n_duration = off
_duration * (stock_freq - freq) / freq
*
*
* o
n
_duration = (freq * DURATION) / stock_freq
* o
ff
_duration = (freq * DURATION) / stock_freq
* o
ff_duration = DURATION - on
_duration
* o
n_duration = DURATION - off
_duration
*
*
*
*
*---------------------------------------------------------------------------
*---------------------------------------------------------------------------
*
*
* ChangeLog:
* ChangeLog:
* Dec. 12, 2003 Hiroshi Miura <miura@da-cha.org>
* - fix on/off register mistake
* - fix cpu_khz calc when it stops cpu modulation.
*
* Dec. 11, 2002 Hiroshi Miura <miura@da-cha.org>
* Dec. 11, 2002 Hiroshi Miura <miura@da-cha.org>
* - rewrite for Cyrix MediaGX Cx5510/5520 and
* - rewrite for Cyrix MediaGX Cx5510/5520 and
* NatSemi Geode Cs5530(A).
* NatSemi Geode Cs5530(A).
...
@@ -233,13 +237,13 @@ static unsigned int gx_validate_speed(unsigned int khz, u8 *on_duration, u8 *off
...
@@ -233,13 +237,13 @@ static unsigned int gx_validate_speed(unsigned int khz, u8 *on_duration, u8 *off
int
old_tmp_freq
=
stock_freq
;
int
old_tmp_freq
=
stock_freq
;
int
tmp_freq
;
int
tmp_freq
;
*
o
n
_duration
=
1
;
*
o
ff
_duration
=
1
;
*
o
ff
_duration
=
0
;
*
o
n
_duration
=
0
;
for
(
i
=
max_duration
;
i
>
0
;
i
--
)
{
for
(
i
=
max_duration
;
i
>
0
;
i
--
)
{
tmp_o
n
=
((
khz
*
i
)
/
stock_freq
)
&
0xff
;
tmp_o
ff
=
((
khz
*
i
)
/
stock_freq
)
&
0xff
;
tmp_o
ff
=
i
-
tmp_on
;
tmp_o
n
=
i
-
tmp_off
;
tmp_freq
=
(
stock_freq
*
tmp_o
n
)
/
i
;
tmp_freq
=
(
stock_freq
*
tmp_o
ff
)
/
i
;
/* if this relation is closer to khz, use this. If it's equal,
/* if this relation is closer to khz, use this. If it's equal,
* prefer it, too - lower latency */
* prefer it, too - lower latency */
if
(
abs
(
tmp_freq
-
khz
)
<=
abs
(
old_tmp_freq
-
khz
))
{
if
(
abs
(
tmp_freq
-
khz
)
<=
abs
(
old_tmp_freq
-
khz
))
{
...
@@ -273,42 +277,37 @@ static void gx_set_cpuspeed(unsigned int khz)
...
@@ -273,42 +277,37 @@ static void gx_set_cpuspeed(unsigned int khz)
freqs
.
new
=
new_khz
;
freqs
.
new
=
new_khz
;
if
(
new_khz
==
stock_freq
)
{
/* if new khz == 100% of CPU speed, it is special case */
local_irq_save
(
flags
);
cpufreq_notify_transition
(
&
freqs
,
CPUFREQ_PRECHANGE
);
pci_write_config_byte
(
gx_params
->
cs55x0
,
PCI_SUSCFG
,
(
gx_params
->
pci_suscfg
&
~
(
SUSMOD
)));
pci_read_config_byte
(
gx_params
->
cs55x0
,
PCI_SUSCFG
,
&
(
gx_params
->
pci_suscfg
));
local_irq_restore
(
flags
);
dprintk
(
"suspend modulation disabled: cpu runs 100 percent speed.
\n
"
);
cpufreq_notify_transition
(
&
freqs
,
CPUFREQ_POSTCHANGE
);
return
;
}
cpufreq_notify_transition
(
&
freqs
,
CPUFREQ_PRECHANGE
);
cpufreq_notify_transition
(
&
freqs
,
CPUFREQ_PRECHANGE
);
local_irq_save
(
flags
);
local_irq_save
(
flags
);
switch
(
gx_params
->
cs55x0
->
device
)
{
case
PCI_DEVICE_ID_CYRIX_5530_LEGACY
:
if
(
new_khz
!=
stock_freq
)
{
/* if new khz == 100% of CPU speed, it is special case */
pmer1
=
gx_params
->
pci_pmer1
|
IRQ_SPDUP
|
VID_SPDUP
;
switch
(
gx_params
->
cs55x0
->
device
)
{
/* FIXME: need to test other values -- Zwane,Miura */
case
PCI_DEVICE_ID_CYRIX_5530_LEGACY
:
pci_write_config_byte
(
gx_params
->
cs55x0
,
PCI_IRQTC
,
4
);
/* typical 2 to 4ms */
pmer1
=
gx_params
->
pci_pmer1
|
IRQ_SPDUP
|
VID_SPDUP
;
pci_write_config_byte
(
gx_params
->
cs55x0
,
PCI_VIDTC
,
100
);
/* typical 50 to 100ms */
/* FIXME: need to test other values -- Zwane,Miura */
pci_write_config_byte
(
gx_params
->
cs55x0
,
PCI_PMER1
,
pmer1
);
pci_write_config_byte
(
gx_params
->
cs55x0
,
PCI_IRQTC
,
4
);
/* typical 2 to 4ms */
pci_write_config_byte
(
gx_params
->
cs55x0
,
PCI_VIDTC
,
100
);
/* typical 50 to 100ms */
if
(
gx_params
->
pci_rev
<
0x10
)
{
/* CS5530(rev 1.2, 1.3) */
pci_write_config_byte
(
gx_params
->
cs55x0
,
PCI_PMER1
,
pmer1
);
if
(
gx_params
->
pci_rev
<
0x10
)
{
/* CS5530(rev 1.2, 1.3) */
suscfg
=
gx_params
->
pci_suscfg
|
SUSMOD
;
}
else
{
/* CS5530A,B.. */
suscfg
=
gx_params
->
pci_suscfg
|
SUSMOD
|
PWRSVE
;
}
break
;
case
PCI_DEVICE_ID_CYRIX_5520
:
case
PCI_DEVICE_ID_CYRIX_5510
:
suscfg
=
gx_params
->
pci_suscfg
|
SUSMOD
;
suscfg
=
gx_params
->
pci_suscfg
|
SUSMOD
;
}
else
{
/* CS5530A,B.. */
default:
suscfg
=
gx_params
->
pci_suscfg
|
SUSMOD
|
PWRSVE
;
local_irq_restore
(
flags
);
dprintk
(
"fatal: try to set unknown chipset.
\n
"
);
return
;
}
}
break
;
}
else
{
case
PCI_DEVICE_ID_CYRIX_5520
:
suscfg
=
gx_params
->
pci_suscfg
&
~
(
SUSMOD
);
case
PCI_DEVICE_ID_CYRIX_5510
:
gx_params
->
off_duration
=
0
;
suscfg
=
gx_params
->
pci_suscfg
|
SUSMOD
;
gx_params
->
on_duration
=
0
;
break
;
dprintk
(
"suspend modulation disabled: cpu runs 100 percent speed.
\n
"
);
default:
local_irq_restore
(
flags
);
dprintk
(
"fatal: try to set unknown chipset.
\n
"
);
return
;
}
}
pci_write_config_byte
(
gx_params
->
cs55x0
,
PCI_MODOFF
,
gx_params
->
off_duration
);
pci_write_config_byte
(
gx_params
->
cs55x0
,
PCI_MODOFF
,
gx_params
->
off_duration
);
...
...
arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
View file @
33ab1d91
...
@@ -246,7 +246,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
...
@@ -246,7 +246,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
static
int
cpufreq_p4_cpu_exit
(
struct
cpufreq_policy
*
policy
)
static
int
cpufreq_p4_cpu_exit
(
struct
cpufreq_policy
*
policy
)
{
{
cpufreq_frequency_table_put_attr
(
policy
->
cpu
);
cpufreq_frequency_table_put_attr
(
policy
->
cpu
);
return
cpufreq_p4_setdc
(
policy
->
cpu
,
DC_DISABLE
)
;
return
0
;
}
}
static
struct
freq_attr
*
p4clockmod_attr
[]
=
{
static
struct
freq_attr
*
p4clockmod_attr
[]
=
{
...
...
arch/i386/kernel/cpu/cpufreq/powernow-k7.c
View file @
33ab1d91
...
@@ -91,18 +91,13 @@ static int check_powernow(void)
...
@@ -91,18 +91,13 @@ static int check_powernow(void)
struct
cpuinfo_x86
*
c
=
cpu_data
;
struct
cpuinfo_x86
*
c
=
cpu_data
;
unsigned
int
maxei
,
eax
,
ebx
,
ecx
,
edx
;
unsigned
int
maxei
,
eax
,
ebx
,
ecx
,
edx
;
if
(
c
->
x86_vendor
!=
X86_VENDOR_AMD
)
{
if
((
c
->
x86_vendor
!=
X86_VENDOR_AMD
)
||
(
c
->
x86
!=
6
))
{
printk
(
KERN_INFO
PFX
"AMD processor not detected.
\n
"
);
#ifdef MODULE
return
0
;
}
if
(
c
->
x86
!=
6
)
{
printk
(
KERN_INFO
PFX
"This module only works with AMD K7 CPUs
\n
"
);
printk
(
KERN_INFO
PFX
"This module only works with AMD K7 CPUs
\n
"
);
#endif
return
0
;
return
0
;
}
}
printk
(
KERN_INFO
PFX
"AMD K7 CPU detected.
\n
"
);
if
((
c
->
x86_model
==
6
)
&&
(
c
->
x86_mask
==
0
))
{
if
((
c
->
x86_model
==
6
)
&&
(
c
->
x86_mask
==
0
))
{
printk
(
KERN_INFO
PFX
"K7 660[A0] core detected, enabling errata workarounds
\n
"
);
printk
(
KERN_INFO
PFX
"K7 660[A0] core detected, enabling errata workarounds
\n
"
);
have_a0
=
1
;
have_a0
=
1
;
...
...
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
View file @
33ab1d91
...
@@ -31,7 +31,7 @@
...
@@ -31,7 +31,7 @@
#define PFX "powernow-k8: "
#define PFX "powernow-k8: "
#define BFX PFX "BIOS error: "
#define BFX PFX "BIOS error: "
#define VERSION "version 1.00.08
- September 26, 2003
"
#define VERSION "version 1.00.08
a
"
#include "powernow-k8.h"
#include "powernow-k8.h"
#ifdef CONFIG_PREEMPT
#ifdef CONFIG_PREEMPT
...
@@ -44,10 +44,11 @@ static u32 numps; /* number of p-states, from PSB */
...
@@ -44,10 +44,11 @@ static u32 numps; /* number of p-states, from PSB */
static
u32
rvo
;
/* ramp voltage offset, from PSB */
static
u32
rvo
;
/* ramp voltage offset, from PSB */
static
u32
irt
;
/* isochronous relief time, from PSB */
static
u32
irt
;
/* isochronous relief time, from PSB */
static
u32
vidmvs
;
/* usable value calculated from mvs, from PSB */
static
u32
vidmvs
;
/* usable value calculated from mvs, from PSB */
struct
pst_s
*
ppst
;
/* array of p states, valid for this part */
static
u32
currvid
;
/* keep track of the current fid / vid */
static
u32
currvid
;
/* keep track of the current fid / vid */
static
u32
currfid
;
static
u32
currfid
;
static
struct
cpufreq_frequency_table
*
powernow_table
;
/*
/*
The PSB table supplied by BIOS allows for the definition of the number of
The PSB table supplied by BIOS allows for the definition of the number of
p-states that can be used when running on a/c, and the number of p-states
p-states that can be used when running on a/c, and the number of p-states
...
@@ -71,30 +72,12 @@ so this is not actually a restriction.
...
@@ -71,30 +72,12 @@ so this is not actually a restriction.
static
u32
batps
;
/* limit on the number of p states when on battery */
static
u32
batps
;
/* limit on the number of p states when on battery */
/* - set by BIOS in the PSB/PST */
/* - set by BIOS in the PSB/PST */
static
struct
cpufreq_driver
cpufreq_amd64_driver
=
{
/* Return a frequency in MHz, given an input fid */
.
verify
=
powernowk8_verify
,
static
u32
find_freq_from_fid
(
u32
fid
)
.
target
=
powernowk8_target
,
.
init
=
powernowk8_cpu_init
,
.
name
=
"cpufreq-amd64"
,
.
owner
=
THIS_MODULE
,
};
#define SEARCH_UP 1
#define SEARCH_DOWN 0
/* Return a frequency in MHz, given an input fid */
u32
find_freq_from_fid
(
u32
fid
)
{
{
return
800
+
(
fid
*
100
);
return
800
+
(
fid
*
100
);
}
}
/* Return a fid matching an input frequency in MHz */
static
u32
find_fid_from_freq
(
u32
freq
)
{
return
(
freq
-
800
)
/
100
;
}
/* Return the vco fid for an input fid */
/* Return the vco fid for an input fid */
static
u32
static
u32
...
@@ -107,56 +90,27 @@ convert_fid_to_vco_fid(u32 fid)
...
@@ -107,56 +90,27 @@ convert_fid_to_vco_fid(u32 fid)
}
}
}
}
/* Sort the fid/vid frequency table into ascending order by fid. The spec */
/*
/* implies that it will be sorted by BIOS, but, it only implies it, and I */
* Return 1 if the pending bit is set. Unless we are actually just told the
/* prefer not to trust when I can check. */
* processor to transition a state, seeing this bit set is really bad news.
/* Yes, it is a simple bubble sort, but the PST is really small, so the */
*/
/* choice of algorithm is pretty irrelevant. */
static
inline
void
sort_pst
(
struct
pst_s
*
ppst
,
u32
numpstates
)
{
u32
i
;
u8
tempfid
;
u8
tempvid
;
int
swaps
=
1
;
while
(
swaps
)
{
swaps
=
0
;
for
(
i
=
0
;
i
<
(
numpstates
-
1
);
i
++
)
{
if
(
ppst
[
i
].
fid
>
ppst
[
i
+
1
].
fid
)
{
swaps
=
1
;
tempfid
=
ppst
[
i
].
fid
;
tempvid
=
ppst
[
i
].
vid
;
ppst
[
i
].
fid
=
ppst
[
i
+
1
].
fid
;
ppst
[
i
].
vid
=
ppst
[
i
+
1
].
vid
;
ppst
[
i
+
1
].
fid
=
tempfid
;
ppst
[
i
+
1
].
vid
=
tempvid
;
}
}
}
return
;
}
/* Return 1 if the pending bit is set. Unless we are actually just told the */
/* processor to transition a state, seeing this bit set is really bad news. */
static
inline
int
static
inline
int
pending_bit_stuck
(
void
)
pending_bit_stuck
(
void
)
{
{
u32
lo
;
u32
lo
,
hi
;
u32
hi
;
rdmsr
(
MSR_FIDVID_STATUS
,
lo
,
hi
);
rdmsr
(
MSR_FIDVID_STATUS
,
lo
,
hi
);
return
lo
&
MSR_S_LO_CHANGE_PENDING
?
1
:
0
;
return
lo
&
MSR_S_LO_CHANGE_PENDING
?
1
:
0
;
}
}
/* Update the global current fid / vid values from the status msr. Returns 1 */
/*
/* on error. */
* Update the global current fid / vid values from the status msr. Returns 1
* on error.
*/
static
int
static
int
query_current_values_with_pending_wait
(
void
)
query_current_values_with_pending_wait
(
void
)
{
{
u32
lo
;
u32
lo
,
hi
;
u32
hi
;
u32
i
=
0
;
u32
i
=
0
;
lo
=
MSR_S_LO_CHANGE_PENDING
;
lo
=
MSR_S_LO_CHANGE_PENDING
;
...
@@ -271,9 +225,11 @@ write_new_vid(u32 vid)
...
@@ -271,9 +225,11 @@ write_new_vid(u32 vid)
return
0
;
return
0
;
}
}
/* Reduce the vid by the max of step or reqvid. */
/*
/* Decreasing vid codes represent increasing voltages : */
* Reduce the vid by the max of step or reqvid.
/* vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of 0x1f is off. */
* Decreasing vid codes represent increasing voltages:
* vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of 0x1f is off.
*/
static
int
static
int
decrease_vid_code_by_step
(
u32
reqvid
,
u32
step
)
decrease_vid_code_by_step
(
u32
reqvid
,
u32
step
)
{
{
...
@@ -316,8 +272,10 @@ transition_fid_vid(u32 reqfid, u32 reqvid)
...
@@ -316,8 +272,10 @@ transition_fid_vid(u32 reqfid, u32 reqvid)
return
0
;
return
0
;
}
}
/* Phase 1 - core voltage transition ... setup appropriate voltage for the */
/*
/* fid transition. */
* Phase 1 - core voltage transition ... setup appropriate voltage for the
* fid transition.
*/
static
inline
int
static
inline
int
core_voltage_pre_transition
(
u32
reqvid
)
core_voltage_pre_transition
(
u32
reqvid
)
{
{
...
@@ -500,7 +458,9 @@ check_supported_cpu(void)
...
@@ -500,7 +458,9 @@ check_supported_cpu(void)
}
}
if
(
c
->
x86_vendor
!=
X86_VENDOR_AMD
)
{
if
(
c
->
x86_vendor
!=
X86_VENDOR_AMD
)
{
#ifdef MODULE
printk
(
KERN_INFO
PFX
"Not an AMD processor
\n
"
);
printk
(
KERN_INFO
PFX
"Not an AMD processor
\n
"
);
#endif
return
0
;
return
0
;
}
}
...
@@ -533,20 +493,59 @@ check_supported_cpu(void)
...
@@ -533,20 +493,59 @@ check_supported_cpu(void)
return
0
;
return
0
;
}
}
printk
(
KERN_INFO
PFX
"Found AMD Athlon 64 / Opteron processor "
printk
(
KERN_INFO
PFX
"Found AMD64 processor supporting PowerNow ("
VERSION
")
\n
"
);
"supporting p-state transitions
\n
"
);
return
1
;
return
1
;
}
}
static
int
check_pst_table
(
struct
pst_s
*
pst
,
u8
maxvid
)
{
unsigned
int
j
;
u8
lastfid
=
0xFF
;
for
(
j
=
0
;
j
<
numps
;
j
++
)
{
if
(
pst
[
j
].
vid
>
LEAST_VID
)
{
printk
(
KERN_ERR
PFX
"vid %d invalid : 0x%x
\n
"
,
j
,
pst
[
j
].
vid
);
return
-
EINVAL
;
}
if
(
pst
[
j
].
vid
<
rvo
)
{
/* vid + rvo >= 0 */
printk
(
KERN_ERR
PFX
"BIOS error - 0 vid exceeded with pstate %d
\n
"
,
j
);
return
-
ENODEV
;
}
if
(
pst
[
j
].
vid
<
maxvid
+
rvo
)
{
/* vid + rvo >= maxvid */
printk
(
KERN_ERR
PFX
"BIOS error - maxvid exceeded with pstate %d
\n
"
,
j
);
return
-
ENODEV
;
}
if
((
pst
[
j
].
fid
>
MAX_FID
)
||
(
pst
[
j
].
fid
&
1
)
||
(
pst
[
j
].
fid
<
HI_FID_TABLE_BOTTOM
)){
printk
(
KERN_ERR
PFX
"fid %d invalid : 0x%x
\n
"
,
j
,
pst
[
j
].
fid
);
return
-
EINVAL
;
}
if
(
pst
[
j
].
fid
<
lastfid
)
lastfid
=
pst
[
j
].
fid
;
}
if
(
lastfid
&
1
)
{
printk
(
KERN_ERR
PFX
"lastfid invalid
\n
"
);
return
-
EINVAL
;
}
if
(
lastfid
>
LO_FID_TABLE_TOP
)
{
printk
(
KERN_INFO
PFX
"first fid not from lo freq table
\n
"
);
}
return
0
;
}
/* Find and validate the PSB/PST table in BIOS. */
/* Find and validate the PSB/PST table in BIOS. */
static
inline
int
static
inline
int
find_psb_table
(
void
)
find_psb_table
(
void
)
{
{
struct
psb_s
*
psb
;
struct
psb_s
*
psb
;
struct
pst_s
*
pst
;
struct
pst_s
*
pst
;
unsigned
i
,
j
;
unsigned
int
i
,
j
;
u32
lastfid
;
u32
mvs
;
u32
mvs
;
u8
maxvid
;
u8
maxvid
;
...
@@ -573,33 +572,19 @@ find_psb_table(void)
...
@@ -573,33 +572,19 @@ find_psb_table(void)
}
}
vstable
=
psb
->
voltagestabilizationtime
;
vstable
=
psb
->
voltagestabilizationtime
;
printk
(
KERN_INFO
PFX
"voltage stable time: %d (units 20us)
\n
"
,
vstable
);
dprintk
(
KERN_DEBUG
PFX
"flags2: 0x%x
\n
"
,
psb
->
flags2
);
dprintk
(
KERN_DEBUG
PFX
"flags2: 0x%x
\n
"
,
psb
->
flags2
);
rvo
=
psb
->
flags2
&
3
;
rvo
=
psb
->
flags2
&
3
;
irt
=
((
psb
->
flags2
)
>>
2
)
&
3
;
irt
=
((
psb
->
flags2
)
>>
2
)
&
3
;
mvs
=
((
psb
->
flags2
)
>>
4
)
&
3
;
mvs
=
((
psb
->
flags2
)
>>
4
)
&
3
;
vidmvs
=
1
<<
mvs
;
vidmvs
=
1
<<
mvs
;
batps
=
((
psb
->
flags2
)
>>
6
)
&
3
;
batps
=
((
psb
->
flags2
)
>>
6
)
&
3
;
printk
(
KERN_INFO
PFX
"p states on battery: %d "
,
batps
);
switch
(
batps
)
{
printk
(
KERN_INFO
PFX
"voltage stable in %d usec"
,
vstable
*
20
);
case
0
:
if
(
batps
)
printk
(
"- all available
\n
"
);
printk
(
", only %d lowest states on battery"
,
batps
);
break
;
printk
(
", ramp voltage offset: %d"
,
rvo
);
case
1
:
printk
(
", isochronous relief time: %d"
,
irt
);
printk
(
"- only the minimum
\n
"
);
printk
(
", maximum voltage step: %d
\n
"
,
mvs
);
break
;
case
2
:
printk
(
"- only the 2 lowest
\n
"
);
break
;
case
3
:
printk
(
"- only the 3 lowest
\n
"
);
break
;
}
printk
(
KERN_INFO
PFX
"ramp voltage offset: %d
\n
"
,
rvo
);
printk
(
KERN_INFO
PFX
"isochronous relief time: %d
\n
"
,
irt
);
printk
(
KERN_INFO
PFX
"maximum voltage step: %d
\n
"
,
mvs
);
dprintk
(
KERN_DEBUG
PFX
"numpst: 0x%x
\n
"
,
psb
->
numpst
);
dprintk
(
KERN_DEBUG
PFX
"numpst: 0x%x
\n
"
,
psb
->
numpst
);
if
(
psb
->
numpst
!=
1
)
{
if
(
psb
->
numpst
!=
1
)
{
...
@@ -610,14 +595,13 @@ find_psb_table(void)
...
@@ -610,14 +595,13 @@ find_psb_table(void)
dprintk
(
KERN_DEBUG
PFX
"cpuid: 0x%x
\n
"
,
psb
->
cpuid
);
dprintk
(
KERN_DEBUG
PFX
"cpuid: 0x%x
\n
"
,
psb
->
cpuid
);
plllock
=
psb
->
plllocktime
;
plllock
=
psb
->
plllocktime
;
printk
(
KERN_INFO
PFX
"pll lock time: 0x%x
\n
"
,
plllock
);
printk
(
KERN_INFO
PFX
"pll lock time: 0x%x
,
"
,
plllock
);
maxvid
=
psb
->
maxvid
;
maxvid
=
psb
->
maxvid
;
printk
(
KERN_INFO
PFX
"maxfid: 0x%x
\n
"
,
psb
->
maxfid
);
printk
(
"maxfid 0x%x (%d MHz), maxvid 0x%x
\n
"
,
printk
(
KERN_INFO
PFX
"maxvid: 0x%x
\n
"
,
maxvid
);
psb
->
maxfid
,
find_freq_from_fid
(
psb
->
maxfid
)
,
maxvid
);
numps
=
psb
->
numpstates
;
numps
=
psb
->
numpstates
;
printk
(
KERN_INFO
PFX
"numpstates: 0x%x
\n
"
,
numps
);
if
(
numps
<
2
)
{
if
(
numps
<
2
)
{
printk
(
KERN_ERR
BFX
"no p states to transition
\n
"
);
printk
(
KERN_ERR
BFX
"no p states to transition
\n
"
);
return
-
ENODEV
;
return
-
ENODEV
;
...
@@ -636,78 +620,41 @@ find_psb_table(void)
...
@@ -636,78 +620,41 @@ find_psb_table(void)
"%d p-states
\n
"
,
numps
);
"%d p-states
\n
"
,
numps
);
}
}
if
(
(
numps
<=
1
)
||
(
batps
<=
1
)
)
{
if
(
numps
<=
1
)
{
printk
(
KERN_ERR
PFX
"only 1 p-state to transition
\n
"
);
printk
(
KERN_ERR
PFX
"only 1 p-state to transition
\n
"
);
return
-
ENODEV
;
return
-
ENODEV
;
}
}
ppst
=
kmalloc
(
sizeof
(
struct
pst_s
)
*
numps
,
GFP_KERNEL
);
if
(
!
ppst
)
{
printk
(
KERN_ERR
PFX
"ppst memory alloc failure
\n
"
);
return
-
ENOMEM
;
}
pst
=
(
struct
pst_s
*
)
(
psb
+
1
);
pst
=
(
struct
pst_s
*
)
(
psb
+
1
);
for
(
j
=
0
;
j
<
numps
;
j
++
)
{
if
(
check_pst_table
(
pst
,
maxvid
))
ppst
[
j
].
fid
=
pst
[
j
].
fid
;
return
-
EINVAL
;
ppst
[
j
].
vid
=
pst
[
j
].
vid
;
printk
(
KERN_INFO
PFX
" %d : fid 0x%x, vid 0x%x
\n
"
,
j
,
ppst
[
j
].
fid
,
ppst
[
j
].
vid
);
}
sort_pst
(
ppst
,
numps
);
lastfid
=
ppst
[
0
].
fid
;
if
(
lastfid
>
LO_FID_TABLE_TOP
)
printk
(
KERN_INFO
BFX
"first fid not in lo freq tbl
\n
"
);
if
((
lastfid
>
MAX_FID
)
||
(
lastfid
&
1
)
||
(
ppst
[
0
].
vid
>
LEAST_VID
))
{
printk
(
KERN_ERR
BFX
"first fid/vid bad (0x%x - 0x%x)
\n
"
,
lastfid
,
ppst
[
0
].
vid
);
kfree
(
ppst
);
return
-
ENODEV
;
}
for
(
j
=
1
;
j
<
numps
;
j
++
)
{
powernow_table
=
kmalloc
((
sizeof
(
struct
cpufreq_frequency_table
)
*
(
numps
+
1
)),
GFP_KERNEL
);
if
((
lastfid
>=
ppst
[
j
].
fid
)
if
(
!
powernow_table
)
{
||
(
ppst
[
j
].
fid
&
1
)
printk
(
KERN_ERR
PFX
"powernow_table memory alloc failure
\n
"
);
||
(
ppst
[
j
].
fid
<
HI_FID_TABLE_BOTTOM
)
return
-
ENOMEM
;
||
(
ppst
[
j
].
fid
>
MAX_FID
)
||
(
ppst
[
j
].
vid
>
LEAST_VID
))
{
printk
(
KERN_ERR
BFX
"invalid fid/vid in pst(%x %x)
\n
"
,
ppst
[
j
].
fid
,
ppst
[
j
].
vid
);
kfree
(
ppst
);
return
-
ENODEV
;
}
lastfid
=
ppst
[
j
].
fid
;
}
}
for
(
j
=
0
;
j
<
numps
;
j
++
)
{
for
(
j
=
0
;
j
<
numps
;
j
++
)
{
if
(
ppst
[
j
].
vid
<
rvo
)
{
/* vid+rvo >= 0 */
printk
(
KERN_INFO
PFX
" %d : fid 0x%x (%d MHz), vid 0x%x
\n
"
,
j
,
printk
(
KERN_ERR
BFX
pst
[
j
].
fid
,
find_freq_from_fid
(
pst
[
j
].
fid
),
pst
[
j
].
vid
);
"0 vid exceeded with pstate %d
\n
"
,
j
);
powernow_table
[
j
].
index
=
pst
[
j
].
fid
;
/* lower 8 bits */
kfree
(
ppst
);
powernow_table
[
j
].
index
|=
(
pst
[
j
].
vid
<<
8
);
/* upper 8 bits */
return
-
ENODEV
;
powernow_table
[
j
].
frequency
=
find_freq_from_fid
(
pst
[
j
].
fid
);
}
if
(
ppst
[
j
].
vid
<
maxvid
+
rvo
)
{
/* vid+rvo >= maxvid */
printk
(
KERN_ERR
BFX
"maxvid exceeded with pstate %d
\n
"
,
j
);
kfree
(
ppst
);
return
-
ENODEV
;
}
}
}
powernow_table
[
numps
].
frequency
=
CPUFREQ_TABLE_END
;
powernow_table
[
numps
].
index
=
0
;
if
(
query_current_values_with_pending_wait
())
{
if
(
query_current_values_with_pending_wait
())
{
kfree
(
p
pst
);
kfree
(
p
owernow_table
);
return
-
EIO
;
return
-
EIO
;
}
}
printk
(
KERN_INFO
PFX
"currfid 0x%x, currvid 0x%x
\n
"
,
printk
(
KERN_INFO
PFX
"currfid 0x%x
(%d MHz)
, currvid 0x%x
\n
"
,
currfid
,
currvid
);
currfid
,
find_freq_from_fid
(
currfid
),
currvid
);
for
(
j
=
0
;
j
<
numps
;
j
++
)
for
(
j
=
0
;
j
<
numps
;
j
++
)
if
((
p
pst
[
j
].
fid
==
currfid
)
&&
(
p
pst
[
j
].
vid
==
currvid
))
if
((
p
st
[
j
].
fid
==
currfid
)
&&
(
pst
[
j
].
vid
==
currvid
))
return
0
;
return
0
;
printk
(
KERN_ERR
BFX
"currfid/vid do not match PST, ignoring
\n
"
);
printk
(
KERN_ERR
BFX
"currfid/vid do not match PST, ignoring
\n
"
);
...
@@ -718,112 +665,22 @@ find_psb_table(void)
...
@@ -718,112 +665,22 @@ find_psb_table(void)
return
-
ENODEV
;
return
-
ENODEV
;
}
}
/* Converts a frequency (that might not necessarily be a multiple of 200) */
/* to a fid. */
static
u32
find_closest_fid
(
u32
freq
,
int
searchup
)
{
if
(
searchup
==
SEARCH_UP
)
freq
+=
MIN_FREQ_RESOLUTION
-
1
;
freq
=
(
freq
/
MIN_FREQ_RESOLUTION
)
*
MIN_FREQ_RESOLUTION
;
if
(
freq
<
MIN_FREQ
)
freq
=
MIN_FREQ
;
else
if
(
freq
>
MAX_FREQ
)
freq
=
MAX_FREQ
;
return
find_fid_from_freq
(
freq
);
}
static
int
find_match
(
u32
*
ptargfreq
,
u32
*
pmin
,
u32
*
pmax
,
int
searchup
,
u32
*
pfid
,
u32
*
pvid
)
{
u32
availpstates
=
batps
;
u32
targfid
=
find_closest_fid
(
*
ptargfreq
,
searchup
);
u32
minfid
=
find_closest_fid
(
*
pmin
,
SEARCH_DOWN
);
u32
maxfid
=
find_closest_fid
(
*
pmax
,
SEARCH_UP
);
u32
minidx
=
0
;
u32
maxidx
=
availpstates
-
1
;
u32
targidx
=
0xffffffff
;
int
i
;
dprintk
(
KERN_DEBUG
PFX
"find match: freq %d MHz, min %d, max %d
\n
"
,
*
ptargfreq
,
*
pmin
,
*
pmax
);
/* Restrict values to the frequency choices in the PST */
if
(
minfid
<
ppst
[
0
].
fid
)
minfid
=
ppst
[
0
].
fid
;
if
(
maxfid
>
ppst
[
maxidx
].
fid
)
maxfid
=
ppst
[
maxidx
].
fid
;
/* Find appropriate PST index for the minimim fid */
for
(
i
=
0
;
i
<
(
int
)
availpstates
;
i
++
)
{
if
(
minfid
>=
ppst
[
i
].
fid
)
minidx
=
i
;
}
/* Find appropriate PST index for the maximum fid */
for
(
i
=
availpstates
-
1
;
i
>=
0
;
i
--
)
{
if
(
maxfid
<=
ppst
[
i
].
fid
)
maxidx
=
i
;
}
if
(
minidx
>
maxidx
)
maxidx
=
minidx
;
/* Frequency ids are now constrained by limits matching PST entries */
minfid
=
ppst
[
minidx
].
fid
;
maxfid
=
ppst
[
maxidx
].
fid
;
/* Limit the target frequency to these limits */
if
(
targfid
<
minfid
)
targfid
=
minfid
;
else
if
(
targfid
>
maxfid
)
targfid
=
maxfid
;
/* Find the best target index into the PST, contrained by the range */
if
(
searchup
==
SEARCH_UP
)
{
for
(
i
=
maxidx
;
i
>=
(
int
)
minidx
;
i
--
)
{
if
(
targfid
<=
ppst
[
i
].
fid
)
targidx
=
i
;
}
}
else
{
for
(
i
=
minidx
;
i
<=
(
int
)
maxidx
;
i
++
)
{
if
(
targfid
>=
ppst
[
i
].
fid
)
targidx
=
i
;
}
}
if
(
targidx
==
0xffffffff
)
{
printk
(
KERN_ERR
PFX
"could not find target
\n
"
);
return
1
;
}
*
pmin
=
find_freq_from_fid
(
minfid
);
*
pmax
=
find_freq_from_fid
(
maxfid
);
*
ptargfreq
=
find_freq_from_fid
(
ppst
[
targidx
].
fid
);
if
(
pfid
)
*
pfid
=
ppst
[
targidx
].
fid
;
if
(
pvid
)
*
pvid
=
ppst
[
targidx
].
vid
;
return
0
;
}
/* Take a frequency, and issue the fid/vid transition command */
/* Take a frequency, and issue the fid/vid transition command */
static
inline
int
static
inline
int
transition_frequency
(
u
32
*
preq
,
u32
*
pmin
,
u32
*
pmax
,
u32
searchup
)
transition_frequency
(
u
nsigned
int
index
)
{
{
u32
fid
;
u32
fid
;
u32
vid
;
u32
vid
;
int
res
;
int
res
;
struct
cpufreq_freqs
freqs
;
struct
cpufreq_freqs
freqs
;
if
(
find_match
(
preq
,
pmin
,
pmax
,
searchup
,
&
fid
,
&
vid
))
/* fid are the lower 8 bits of the index we stored into
return
1
;
* the cpufreq frequency table in find_psb_table, vid are
* the upper 8 bits.
*/
fid
=
powernow_table
[
index
].
index
&
0xFF
;
vid
=
(
powernow_table
[
index
].
index
&
0xFF00
)
>>
8
;
dprintk
(
KERN_DEBUG
PFX
"table matched fid 0x%x, giving vid 0x%x
\n
"
,
dprintk
(
KERN_DEBUG
PFX
"table matched fid 0x%x, giving vid 0x%x
\n
"
,
fid
,
vid
);
fid
,
vid
);
...
@@ -867,14 +724,7 @@ powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relati
...
@@ -867,14 +724,7 @@ powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relati
{
{
u32
checkfid
=
currfid
;
u32
checkfid
=
currfid
;
u32
checkvid
=
currvid
;
u32
checkvid
=
currvid
;
u32
reqfreq
=
targfreq
/
1000
;
unsigned
int
newstate
;
u32
minfreq
=
pol
->
min
/
1000
;
u32
maxfreq
=
pol
->
max
/
1000
;
if
(
ppst
==
0
)
{
printk
(
KERN_ERR
PFX
"targ: ppst 0
\n
"
);
return
-
ENODEV
;
}
if
(
pending_bit_stuck
())
{
if
(
pending_bit_stuck
())
{
printk
(
KERN_ERR
PFX
"drv targ fail: change pending bit set
\n
"
);
printk
(
KERN_ERR
PFX
"drv targ fail: change pending bit set
\n
"
);
...
@@ -896,9 +746,10 @@ powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relati
...
@@ -896,9 +746,10 @@ powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relati
checkfid
,
currfid
,
checkvid
,
currvid
);
checkfid
,
currfid
,
checkvid
,
currvid
);
}
}
if
(
transition_frequency
(
&
reqfreq
,
&
minfreq
,
&
maxfreq
,
if
(
cpufreq_frequency_table_target
(
pol
,
powernow_table
,
targfreq
,
relation
,
&
newstate
))
relation
==
return
-
EINVAL
;
CPUFREQ_RELATION_H
?
SEARCH_UP
:
SEARCH_DOWN
))
if
(
transition_frequency
(
newstate
))
{
{
printk
(
KERN_ERR
PFX
"transition frequency failed
\n
"
);
printk
(
KERN_ERR
PFX
"transition frequency failed
\n
"
);
return
1
;
return
1
;
...
@@ -913,36 +764,12 @@ powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relati
...
@@ -913,36 +764,12 @@ powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relati
static
int
static
int
powernowk8_verify
(
struct
cpufreq_policy
*
pol
)
powernowk8_verify
(
struct
cpufreq_policy
*
pol
)
{
{
u32
min
=
pol
->
min
/
1000
;
u32
max
=
pol
->
max
/
1000
;
u32
targ
=
min
;
int
res
;
if
(
ppst
==
0
)
{
printk
(
KERN_ERR
PFX
"verify - ppst 0
\n
"
);
return
-
ENODEV
;
}
if
(
pending_bit_stuck
())
{
if
(
pending_bit_stuck
())
{
printk
(
KERN_ERR
PFX
"failing verify, change pending bit set
\n
"
);
printk
(
KERN_ERR
PFX
"failing verify, change pending bit set
\n
"
);
return
-
EIO
;
return
-
EIO
;
}
}
dprintk
(
KERN_DEBUG
PFX
return
cpufreq_frequency_table_verify
(
pol
,
powernow_table
);
"ver: cpu%d, min %d, max %d, cur %d, pol %d
\n
"
,
pol
->
cpu
,
pol
->
min
,
pol
->
max
,
pol
->
cur
,
pol
->
policy
);
if
(
pol
->
cpu
!=
0
)
{
printk
(
KERN_ERR
PFX
"verify - cpu not 0
\n
"
);
return
-
ENODEV
;
}
res
=
find_match
(
&
targ
,
&
min
,
&
max
,
SEARCH_DOWN
,
0
,
0
);
if
(
!
res
)
{
pol
->
min
=
min
*
1000
;
pol
->
max
=
max
*
1000
;
}
return
res
;
}
}
/* per CPU init entry point to the driver */
/* per CPU init entry point to the driver */
...
@@ -968,10 +795,11 @@ powernowk8_cpu_init(struct cpufreq_policy *pol)
...
@@ -968,10 +795,11 @@ powernowk8_cpu_init(struct cpufreq_policy *pol)
dprintk
(
KERN_DEBUG
PFX
"policy current frequency %d kHz
\n
"
,
pol
->
cur
);
dprintk
(
KERN_DEBUG
PFX
"policy current frequency %d kHz
\n
"
,
pol
->
cur
);
/* min/max the cpu is capable of */
/* min/max the cpu is capable of */
pol
->
cpuinfo
.
min_freq
=
1000
*
find_freq_from_fid
(
ppst
[
0
].
fid
);
if
(
cpufreq_frequency_table_cpuinfo
(
pol
,
powernow_table
))
{
pol
->
cpuinfo
.
max_freq
=
1000
*
find_freq_from_fid
(
ppst
[
numps
-
1
].
fid
);
printk
(
KERN_ERR
PFX
"invalid powernow_table
\n
"
);
pol
->
min
=
1000
*
find_freq_from_fid
(
ppst
[
0
].
fid
);
kfree
(
powernow_table
);
pol
->
max
=
1000
*
find_freq_from_fid
(
ppst
[
batps
-
1
].
fid
);
return
-
EINVAL
;
}
printk
(
KERN_INFO
PFX
"cpu_init done, current fid 0x%x, vid 0x%x
\n
"
,
printk
(
KERN_INFO
PFX
"cpu_init done, current fid 0x%x, vid 0x%x
\n
"
,
currfid
,
currvid
);
currfid
,
currvid
);
...
@@ -979,14 +807,33 @@ powernowk8_cpu_init(struct cpufreq_policy *pol)
...
@@ -979,14 +807,33 @@ powernowk8_cpu_init(struct cpufreq_policy *pol)
return
0
;
return
0
;
}
}
static
int
__exit
powernowk8_cpu_exit
(
struct
cpufreq_policy
*
pol
)
{
if
(
pol
->
cpu
!=
0
)
return
-
EINVAL
;
if
(
powernow_table
)
kfree
(
powernow_table
);
return
0
;
}
static
struct
cpufreq_driver
cpufreq_amd64_driver
=
{
.
verify
=
powernowk8_verify
,
.
target
=
powernowk8_target
,
.
init
=
powernowk8_cpu_init
,
.
exit
=
powernowk8_cpu_exit
,
.
name
=
"powernow-k8"
,
.
owner
=
THIS_MODULE
,
};
/* driver entry point for init */
/* driver entry point for init */
static
int
__init
static
int
__init
powernowk8_init
(
void
)
powernowk8_init
(
void
)
{
{
int
rc
;
int
rc
;
printk
(
KERN_INFO
PFX
VERSION
"
\n
"
);
if
(
check_supported_cpu
()
==
0
)
if
(
check_supported_cpu
()
==
0
)
return
-
ENODEV
;
return
-
ENODEV
;
...
@@ -996,7 +843,6 @@ powernowk8_init(void)
...
@@ -996,7 +843,6 @@ powernowk8_init(void)
if
(
pending_bit_stuck
())
{
if
(
pending_bit_stuck
())
{
printk
(
KERN_ERR
PFX
"powernowk8_init fail, change pending bit set
\n
"
);
printk
(
KERN_ERR
PFX
"powernowk8_init fail, change pending bit set
\n
"
);
kfree
(
ppst
);
return
-
EIO
;
return
-
EIO
;
}
}
...
@@ -1010,7 +856,6 @@ powernowk8_exit(void)
...
@@ -1010,7 +856,6 @@ powernowk8_exit(void)
dprintk
(
KERN_INFO
PFX
"powernowk8_exit
\n
"
);
dprintk
(
KERN_INFO
PFX
"powernowk8_exit
\n
"
);
cpufreq_unregister_driver
(
&
cpufreq_amd64_driver
);
cpufreq_unregister_driver
(
&
cpufreq_amd64_driver
);
kfree
(
ppst
);
}
}
MODULE_AUTHOR
(
"Paul Devriendt <paul.devriendt@amd.com>"
);
MODULE_AUTHOR
(
"Paul Devriendt <paul.devriendt@amd.com>"
);
...
...
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
View file @
33ab1d91
...
@@ -120,7 +120,3 @@ struct pst_s {
...
@@ -120,7 +120,3 @@ struct pst_s {
static
inline
int
core_voltage_pre_transition
(
u32
reqvid
);
static
inline
int
core_voltage_pre_transition
(
u32
reqvid
);
static
inline
int
core_voltage_post_transition
(
u32
reqvid
);
static
inline
int
core_voltage_post_transition
(
u32
reqvid
);
static
inline
int
core_frequency_transition
(
u32
reqfid
);
static
inline
int
core_frequency_transition
(
u32
reqfid
);
static
int
powernowk8_verify
(
struct
cpufreq_policy
*
pol
);
static
int
powernowk8_target
(
struct
cpufreq_policy
*
pol
,
unsigned
targfreq
,
unsigned
relation
);
static
int
__init
powernowk8_cpu_init
(
struct
cpufreq_policy
*
pol
);
arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
View file @
33ab1d91
...
@@ -207,17 +207,55 @@ unsigned int speedstep_detect_processor (void)
...
@@ -207,17 +207,55 @@ unsigned int speedstep_detect_processor (void)
if
(
c
->
x86_model
!=
2
)
if
(
c
->
x86_model
!=
2
)
return
0
;
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
=
cpuid_ebx
(
0x00000001
);
ebx
&=
0x000000FF
;
ebx
&=
0x000000FF
;
if
((
ebx
!=
0x0e
)
&&
(
ebx
!=
0x0f
))
return
0
;
return
SPEEDSTEP_PROCESSOR_P4M
;
dprintk
(
KERN_INFO
"ebx value is %x, x86_mask is %x
\n
"
,
ebx
,
c
->
86
_mask
);
switch
(
c
->
x86_mask
)
{
case
4
:
/*
* B-stepping [M-P4-M]
* sample has ebx = 0x0f, production has 0x0e.
*/
if
((
ebx
==
0x0e
)
||
(
ebx
==
0x0f
))
return
SPEEDSTEP_PROCESSOR_P4M
;
break
;
case
7
:
/*
* C-stepping [M-P4-M]
* needs to have ebx=0x0e, else it's a celeron:
* cf. 25130917.pdf / page 7, footnote 5 even
* though 25072120.pdf / page 7 doesn't say
* samples are only of B-stepping...
*/
if
(
ebx
==
0x0e
)
return
SPEEDSTEP_PROCESSOR_P4M
;
break
;
case
9
:
/*
* D-stepping [M-P4-M or M-P4/533]
*
* this is totally strange: CPUID 0x0F29 is
* used by M-P4-M, M-P4/533 and(!) Celeron CPUs.
* The latter need to be sorted out as they don't
* support speedstep.
* Celerons with CPUID 0x0F29 may have either
* ebx=0x8 or 0xf -- 25130917.pdf doesn't say anything
* specific.
* M-P4-Ms may have either ebx=0xe or 0xf [see above]
* M-P4/533 have either ebx=0xe or 0xf. [25317607.pdf]
* So, how to distinguish all those processors with
* ebx=0xf? I don't know. Sort them out, and wait
* for someone to complain.
*/
if
(
ebx
==
0x0e
)
return
SPEEDSTEP_PROCESSOR_P4M
;
break
;
default:
break
;
}
return
0
;
}
}
switch
(
c
->
x86_model
)
{
switch
(
c
->
x86_model
)
{
...
...
drivers/cpufreq/cpufreq_userspace.c
View file @
33ab1d91
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* linux/drivers/cpufreq/cpufreq_userspace.c
* linux/drivers/cpufreq/cpufreq_userspace.c
*
*
* Copyright (C) 2001 Russell King
* Copyright (C) 2001 Russell King
* (C) 2002 - 200
3
Dominik Brodowski <linux@brodo.de>
* (C) 2002 - 200
4
Dominik Brodowski <linux@brodo.de>
*
*
* This program is free software; you can redistribute it and/or modify
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* it under the terms of the GNU General Public License version 2 as
...
@@ -112,7 +112,14 @@ int cpufreq_set(unsigned int freq, unsigned int cpu)
...
@@ -112,7 +112,14 @@ int cpufreq_set(unsigned int freq, unsigned int cpu)
if
(
freq
>
cpu_max_freq
[
cpu
])
if
(
freq
>
cpu_max_freq
[
cpu
])
freq
=
cpu_max_freq
[
cpu
];
freq
=
cpu_max_freq
[
cpu
];
ret
=
cpufreq_driver_target
(
&
current_policy
[
cpu
],
freq
,
/*
* We're safe from concurrent calls to ->target() here
* as we hold the userspace_sem lock. If we were calling
* cpufreq_driver_target, a deadlock situation might occur:
* A: cpufreq_set (lock userspace_sem) -> cpufreq_driver_target(lock policy->lock)
* B: cpufreq_set_policy(lock policy->lock) -> __cpufreq_governor -> cpufreq_governor_userspace (lock userspace_sem)
*/
ret
=
__cpufreq_driver_target
(
&
current_policy
[
cpu
],
freq
,
CPUFREQ_RELATION_L
);
CPUFREQ_RELATION_L
);
err:
err:
...
...
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