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
3de581e3
Commit
3de581e3
authored
Apr 06, 2004
by
Dave Jones
Committed by
Dave Jones
Apr 06, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[CPUFREQ] ACPI support for powernow-k8.
We fall back on the legacy PSB table if the ACPI tables don't work out.
parent
ef44e465
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
145 additions
and
15 deletions
+145
-15
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+138
-15
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+7
-0
No files found.
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
View file @
3de581e3
...
@@ -32,6 +32,11 @@
...
@@ -32,6 +32,11 @@
#include <asm/io.h>
#include <asm/io.h>
#include <asm/delay.h>
#include <asm/delay.h>
#ifdef CONFIG_X86_POWERNOW_K8_ACPI
#include <linux/acpi.h>
#include <acpi/processor.h>
#endif
#define PFX "powernow-k8: "
#define PFX "powernow-k8: "
#define BFX PFX "BIOS error: "
#define BFX PFX "BIOS error: "
#define VERSION "version 1.00.08a"
#define VERSION "version 1.00.08a"
...
@@ -661,6 +666,113 @@ static int find_psb_table(struct powernow_k8_data *data)
...
@@ -661,6 +666,113 @@ static int find_psb_table(struct powernow_k8_data *data)
return
-
ENODEV
;
return
-
ENODEV
;
}
}
#ifdef CONFIG_X86_POWERNOW_K8_ACPI
static
void
powernow_k8_acpi_pst_values
(
struct
powernow_k8_data
*
data
,
unsigned
int
index
)
{
if
(
!
data
->
acpi_data
.
state_count
)
return
;
data
->
irt
=
(
data
->
acpi_data
.
states
[
index
].
control
>>
IRT_SHIFT
)
&
IRT_MASK
;
data
->
rvo
=
(
data
->
acpi_data
.
states
[
index
].
control
>>
RVO_SHIFT
)
&
RVO_MASK
;
data
->
plllock
=
(
data
->
acpi_data
.
states
[
index
].
control
>>
PLL_L_SHIFT
)
&
PLL_L_MASK
;
data
->
vidmvs
=
1
<<
((
data
->
acpi_data
.
states
[
index
].
control
>>
MVS_SHIFT
)
&
MVS_MASK
);
data
->
vstable
=
(
data
->
acpi_data
.
states
[
index
].
control
>>
VST_SHIFT
)
&
VST_MASK
;
}
static
int
powernow_k8_cpu_init_acpi
(
struct
powernow_k8_data
*
data
)
{
int
i
;
int
cntlofreq
=
0
;
struct
cpufreq_frequency_table
*
powernow_table
;
if
(
acpi_processor_register_performance
(
&
data
->
acpi_data
,
data
->
cpu
))
{
dprintk
(
KERN_DEBUG
PFX
"register performance failed
\n
"
);
return
-
EIO
;
}
/* verify the data contained in the ACPI structures */
if
(
data
->
acpi_data
.
state_count
<=
1
)
{
dprintk
(
KERN_DEBUG
PFX
"No ACPI P-States
\n
"
);
goto
err_out
;
}
if
((
data
->
acpi_data
.
control_register
.
space_id
!=
ACPI_ADR_SPACE_FIXED_HARDWARE
)
||
(
data
->
acpi_data
.
status_register
.
space_id
!=
ACPI_ADR_SPACE_FIXED_HARDWARE
))
{
dprintk
(
KERN_DEBUG
PFX
"Invalid control/status registers
\n
"
);
goto
err_out
;
}
/* fill in data->powernow_table */
powernow_table
=
kmalloc
((
sizeof
(
struct
cpufreq_frequency_table
)
*
(
data
->
acpi_data
.
state_count
+
1
)),
GFP_KERNEL
);
if
(
!
powernow_table
)
{
dprintk
(
KERN_ERR
PFX
"powernow_table memory alloc failure
\n
"
);
goto
err_out
;
}
for
(
i
=
0
;
i
<
data
->
acpi_data
.
state_count
;
i
++
)
{
u32
fid
=
data
->
acpi_data
.
states
[
i
].
control
&
FID_MASK
;
u32
vid
=
(
data
->
acpi_data
.
states
[
i
].
control
>>
VID_SHIFT
)
&
VID_MASK
;
dprintk
(
KERN_INFO
PFX
" %d : fid %x, vid %x
\n
"
,
i
,
fid
,
vid
);
powernow_table
[
i
].
index
=
fid
;
/* lower 8 bits */
powernow_table
[
i
].
index
|=
(
vid
<<
8
);
/* upper 8 bits */
powernow_table
[
i
].
frequency
=
find_khz_freq_from_fid
(
fid
);
/* verify frequency is OK */
if
((
powernow_table
[
i
].
frequency
>
(
MAX_FREQ
*
1000
))
||
(
powernow_table
[
i
].
frequency
<
(
MIN_FREQ
*
1000
)))
{
dprintk
(
KERN_INFO
PFX
"invalid freq %u kHz
\n
"
,
powernow_table
[
i
].
frequency
);
powernow_table
[
i
].
frequency
=
CPUFREQ_ENTRY_INVALID
;
continue
;
}
/* verify only 1 entry from the lo frequency table */
if
((
fid
<
HI_FID_TABLE_BOTTOM
)
&&
(
cntlofreq
++
))
{
printk
(
KERN_ERR
PFX
"Too many lo freq table entries
\n
"
);
goto
err_out
;
}
if
(
powernow_table
[
i
].
frequency
!=
(
data
->
acpi_data
.
states
[
i
].
core_frequency
*
1000
))
{
printk
(
KERN_INFO
PFX
"invalid freq entries %u kHz vs. %u kHz
\n
"
,
powernow_table
[
i
].
frequency
,
(
unsigned
int
)
(
data
->
acpi_data
.
states
[
i
].
core_frequency
*
1000
));
powernow_table
[
i
].
frequency
=
CPUFREQ_ENTRY_INVALID
;
continue
;
}
}
powernow_table
[
data
->
acpi_data
.
state_count
].
frequency
=
CPUFREQ_TABLE_END
;
powernow_table
[
data
->
acpi_data
.
state_count
].
index
=
0
;
data
->
powernow_table
=
powernow_table
;
/* fill in data */
data
->
numps
=
data
->
acpi_data
.
state_count
;
print_basics
(
data
);
powernow_k8_acpi_pst_values
(
data
,
0
);
return
0
;
err_out:
acpi_processor_unregister_performance
(
&
data
->
acpi_data
,
data
->
cpu
);
/* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */
data
->
acpi_data
.
state_count
=
0
;
return
-
ENODEV
;
}
static
void
powernow_k8_cpu_exit_acpi
(
struct
powernow_k8_data
*
data
)
{
if
(
data
->
acpi_data
.
state_count
)
acpi_processor_unregister_performance
(
&
data
->
acpi_data
,
data
->
cpu
);
}
#else
static
int
powernow_k8_cpu_init_acpi
(
struct
powernow_k8_data
*
data
)
{
return
-
ENODEV
;
}
static
void
powernow_k8_cpu_exit_acpi
(
struct
powernow_k8_data
*
data
)
{
return
;
}
static
void
powernow_k8_acpi_pst_values
(
struct
powernow_k8_data
*
data
,
unsigned
int
index
)
{
return
;
}
#endif
/* CONFIG_X86_POWERNOW_K8_ACPI */
/* Take a frequency, and issue the fid/vid transition command */
/* Take a frequency, and issue the fid/vid transition command */
static
int
transition_frequency
(
struct
powernow_k8_data
*
data
,
unsigned
int
index
)
static
int
transition_frequency
(
struct
powernow_k8_data
*
data
,
unsigned
int
index
)
{
{
...
@@ -767,6 +879,8 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
...
@@ -767,6 +879,8 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
if
(
cpufreq_frequency_table_target
(
pol
,
data
->
powernow_table
,
targfreq
,
relation
,
&
newstate
))
if
(
cpufreq_frequency_table_target
(
pol
,
data
->
powernow_table
,
targfreq
,
relation
,
&
newstate
))
goto
err_out
;
goto
err_out
;
powernow_k8_acpi_pst_values
(
data
,
newstate
);
if
(
transition_frequency
(
data
,
newstate
))
{
if
(
transition_frequency
(
data
,
newstate
))
{
printk
(
KERN_ERR
PFX
"transition frequency failed
\n
"
);
printk
(
KERN_ERR
PFX
"transition frequency failed
\n
"
);
ret
=
1
;
ret
=
1
;
...
@@ -811,6 +925,12 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
...
@@ -811,6 +925,12 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
data
->
cpu
=
pol
->
cpu
;
data
->
cpu
=
pol
->
cpu
;
if
(
powernow_k8_cpu_init_acpi
(
data
))
{
/*
* Use the PSB BIOS structure. This is only availabe on
* an UP version, and is deprecated by AMD.
*/
if
(
pol
->
cpu
!=
0
)
{
if
(
pol
->
cpu
!=
0
)
{
printk
(
KERN_ERR
PFX
"init not cpu 0
\n
"
);
printk
(
KERN_ERR
PFX
"init not cpu 0
\n
"
);
kfree
(
data
);
kfree
(
data
);
...
@@ -826,6 +946,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
...
@@ -826,6 +946,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
kfree
(
data
);
kfree
(
data
);
return
-
ENODEV
;
return
-
ENODEV
;
}
}
}
/* only run on specific CPU from here on */
/* only run on specific CPU from here on */
oldmask
=
current
->
cpus_allowed
;
oldmask
=
current
->
cpus_allowed
;
...
@@ -893,6 +1014,8 @@ static int __exit powernowk8_cpu_exit (struct cpufreq_policy *pol)
...
@@ -893,6 +1014,8 @@ static int __exit powernowk8_cpu_exit (struct cpufreq_policy *pol)
if
(
!
data
)
if
(
!
data
)
return
-
EINVAL
;
return
-
EINVAL
;
powernow_k8_cpu_exit_acpi
(
data
);
cpufreq_frequency_table_put_attr
(
pol
->
cpu
);
cpufreq_frequency_table_put_attr
(
pol
->
cpu
);
kfree
(
data
->
powernow_table
);
kfree
(
data
->
powernow_table
);
...
...
arch/i386/kernel/cpu/cpufreq/powernow-k8.h
View file @
3de581e3
...
@@ -28,6 +28,12 @@ struct powernow_k8_data {
...
@@ -28,6 +28,12 @@ struct powernow_k8_data {
* fid are the lower 8 bits of the index, vid are the upper 8 bits.
* fid are the lower 8 bits of the index, vid are the upper 8 bits.
* frequency is in kHz */
* frequency is in kHz */
struct
cpufreq_frequency_table
*
powernow_table
;
struct
cpufreq_frequency_table
*
powernow_table
;
#ifdef CONFIG_X86_POWERNOW_K8_ACPI
/* the acpi table needs to be kept. it's only available if ACPI was
* used to determine valid frequency/vid/fid states */
struct
acpi_processor_performance
acpi_data
;
#endif
};
};
...
@@ -170,3 +176,4 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
...
@@ -170,3 +176,4 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
static
int
core_voltage_post_transition
(
struct
powernow_k8_data
*
data
,
u32
reqvid
);
static
int
core_voltage_post_transition
(
struct
powernow_k8_data
*
data
,
u32
reqvid
);
static
int
core_frequency_transition
(
struct
powernow_k8_data
*
data
,
u32
reqfid
);
static
int
core_frequency_transition
(
struct
powernow_k8_data
*
data
,
u32
reqfid
);
static
void
powernow_k8_acpi_pst_values
(
struct
powernow_k8_data
*
data
,
unsigned
int
index
);
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