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
94db5ad4
Commit
94db5ad4
authored
Jul 15, 2003
by
Dave Jones
Committed by
Dave Jones
Jul 15, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[CPUFREQ] Clean up longhaul MSR usage using bitfields.
parent
8e94d032
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
113 additions
and
74 deletions
+113
-74
arch/i386/kernel/cpu/cpufreq/longhaul.c
arch/i386/kernel/cpu/cpufreq/longhaul.c
+76
-74
arch/i386/kernel/cpu/cpufreq/longhaul.h
arch/i386/kernel/cpu/cpufreq/longhaul.h
+37
-0
No files found.
arch/i386/kernel/cpu/cpufreq/longhaul.c
View file @
94db5ad4
...
...
@@ -30,6 +30,8 @@
#include <asm/timex.h>
#include <asm/io.h>
#include "longhaul.h"
#define DEBUG
#ifdef DEBUG
...
...
@@ -248,7 +250,7 @@ static int clock_ratio[32];
static
int
eblcr_table
[
32
];
static
int
voltage_table
[
32
];
static
unsigned
int
highest_speed
,
lowest_speed
;
/* kHz */
static
int
longhaul
;
/* version. */
static
int
longhaul
_version
;
static
struct
cpufreq_frequency_table
*
longhaul_table
;
...
...
@@ -273,7 +275,7 @@ static int longhaul_get_cpu_mult (void)
rdmsr
(
MSR_IA32_EBL_CR_POWERON
,
lo
,
hi
);
invalue
=
(
lo
&
(
1
<<
22
|
1
<<
23
|
1
<<
24
|
1
<<
25
))
>>
22
;
if
(
longhaul
==
3
)
{
if
(
longhaul
_version
==
3
)
{
if
(
lo
&
(
1
<<
27
))
invalue
+=
16
;
}
...
...
@@ -290,11 +292,10 @@ static int longhaul_get_cpu_mult (void)
static
void
longhaul_setstate
(
unsigned
int
clock_ratio_index
)
{
unsigned
long
lo
,
hi
;
unsigned
int
bits
;
int
vidindex
,
i
;
struct
cpufreq_freqs
freqs
;
union
msr_longhaul
longhaul
;
if
(
clock_ratio
[
clock_ratio_index
]
==
-
1
)
return
;
...
...
@@ -311,36 +312,35 @@ static void longhaul_setstate (unsigned int clock_ratio_index)
dprintk
(
KERN_INFO
PFX
"FSB:%d Mult(x10):%d
\n
"
,
fsb
*
100
,
clock_ratio
[
clock_ratio_index
]);
bits
=
clock_ratio_index
;
/* "bits" contains the bitpattern of the new multiplier.
we now need to transform it to the desired format. */
switch
(
longhaul
)
{
switch
(
longhaul
_version
)
{
case
1
:
rdmsr
(
MSR_VIA_BCR2
,
lo
,
hi
);
//
rdmsr (MSR_VIA_BCR2, lo, hi);
/* Enable software clock multiplier */
lo
|=
(
1
<<
19
);
//
lo |= (1<<19);
/* desired multiplier */
lo
&=
~
(
1
<<
23
|
1
<<
24
|
1
<<
25
|
1
<<
26
);
lo
|=
(
bits
<<
23
);
wrmsr
(
MSR_VIA_BCR2
,
lo
,
hi
);
//
lo &= ~(1<<23|1<<24|1<<25|1<<26);
//
lo |= (bits<<23);
//
wrmsr (MSR_VIA_BCR2, lo, hi);
__hlt
();
/* Disable software clock multiplier */
rdmsr
(
MSR_VIA_BCR2
,
lo
,
hi
);
lo
&=
~
(
1
<<
19
);
wrmsr
(
MSR_VIA_BCR2
,
lo
,
hi
);
//
rdmsr (MSR_VIA_BCR2, lo, hi);
//
lo &= ~(1<<19);
//
wrmsr (MSR_VIA_BCR2, lo, hi);
break
;
case
2
:
rdmsr
(
MSR_VIA_LONGHAUL
,
lo
,
hi
);
lo
&=
0xfff0bf0f
;
/* reset [19:16,14](bus ratio) and [7:4](rev key) to 0 */
lo
|=
(
bits
<<
16
)
;
lo
|=
(
1
<<
8
);
/* EnableSoftBusRatio */
rdmsr
l
(
MSR_VIA_LONGHAUL
,
longhaul
.
val
);
lo
nghaul
.
bits
.
SoftBusRatio
=
clock_ratio_index
&
0xf
;
lo
nghaul
.
bits
.
SoftBusRatio4
=
(
clock_ratio_index
&
0x10
)
>>
4
;
lo
nghaul
.
bits
.
EnableSoftBusRatio
=
1
;
/* We must program the revision key only with values we
* know about, not blindly copy it from 0:3 */
lo
|
=
1
;
lo
nghaul
.
bits
.
RevisionKey
=
1
;
if
(
can_scale_voltage
)
{
/* PB: TODO fix this up */
...
...
@@ -357,40 +357,39 @@ static void longhaul_setstate (unsigned int clock_ratio_index)
dprintk
(
KERN_INFO
PFX
"Desired vid index=%d
\n
"
,
i
);
#if 0
lo &= 0xfe0fffff;/* reset [24:20](voltage) to 0 */
lo |= (i<<20); /* set voltage */
lo |= (1<<9); /* EnableSoftVID */
longhaul.bits.SoftVID = i;
longhaul.bits.EnableSoftVID = 1;
#endif
}
/* FIXME: Do voltage and freq seperatly like we do in powernow-k7 */
bad_voltage:
wrmsr
(
MSR_VIA_LONGHAUL
,
lo
,
hi
);
wrmsr
l
(
MSR_VIA_LONGHAUL
,
longhaul
.
val
);
__hlt
();
rdmsr
(
MSR_VIA_LONGHAUL
,
lo
,
hi
);
lo
&=
~
(
1
<<
8
)
;
rdmsr
l
(
MSR_VIA_LONGHAUL
,
longhaul
.
val
);
lo
nghaul
.
bits
.
EnableSoftBusRatio
=
0
;
if
(
can_scale_voltage
)
lo
&=
~
(
1
<<
9
)
;
lo
|=
1
;
/* Revision Key */
wrmsr
(
MSR_VIA_LONGHAUL
,
lo
,
hi
);
lo
nghaul
.
bits
.
EnableSoftVID
=
0
;
lo
nghaul
.
bits
.
RevisionKey
=
1
;
wrmsr
l
(
MSR_VIA_LONGHAUL
,
longhaul
.
val
);
break
;
case
3
:
rdmsr
(
MSR_VIA_LONGHAUL
,
lo
,
hi
);
lo
&=
0xfff0bf0f
;
/* reset longhaul[19:16,14] to 0 */
lo
|=
(
bits
<<
16
)
;
lo
|=
(
1
<<
8
);
/* EnableSoftBusRatio */
rdmsr
l
(
MSR_VIA_LONGHAUL
,
longhaul
.
val
);
lo
nghaul
.
bits
.
SoftBusRatio
=
clock_ratio_index
&
0xf
;
lo
nghaul
.
bits
.
SoftBusRatio4
=
(
clock_ratio_index
&
0x10
)
>>
4
;
lo
nghaul
.
bits
.
EnableSoftBusRatio
=
1
;
/* We must program the revision key only with values we
* know about, not blindly copy it from 0:3 */
lo
|
=
3
;
/* SoftVID & SoftBSEL */
lo
nghaul
.
bits
.
RevisionKey
=
3
;
/* SoftVID & SoftBSEL */
wrmsr
(
MSR_VIA_LONGHAUL
,
lo
,
hi
);
wrmsr
l
(
MSR_VIA_LONGHAUL
,
longhaul
.
val
);
__hlt
();
rdmsr
(
MSR_VIA_LONGHAUL
,
lo
,
hi
);
lo
&=
~
(
1
<<
8
)
;
lo
|
=
3
;
wrmsr
(
MSR_VIA_LONGHAUL
,
lo
,
hi
);
rdmsr
l
(
MSR_VIA_LONGHAUL
,
longhaul
.
val
);
lo
nghaul
.
bits
.
EnableSoftBusRatio
=
0
;
lo
nghaul
.
bits
.
RevisionKey
=
3
;
wrmsr
l
(
MSR_VIA_LONGHAUL
,
longhaul
.
val
);
break
;
}
...
...
@@ -400,14 +399,15 @@ static void longhaul_setstate (unsigned int clock_ratio_index)
static
int
__init
longhaul_get_ranges
(
void
)
{
unsigned
long
lo
,
hi
,
invalue
;
unsigned
long
invalue
;
unsigned
int
minmult
=
0
,
maxmult
=
0
;
unsigned
int
multipliers
[
32
]
=
{
50
,
30
,
40
,
100
,
55
,
35
,
45
,
95
,
90
,
70
,
80
,
60
,
120
,
75
,
85
,
65
,
-
1
,
110
,
120
,
-
1
,
135
,
115
,
125
,
105
,
130
,
150
,
160
,
140
,
-
1
,
155
,
-
1
,
145
};
unsigned
int
j
,
k
=
0
;
union
msr_longhaul
longhaul
;
switch
(
longhaul
)
{
switch
(
longhaul
_version
)
{
case
1
:
/* Ugh, Longhaul v1 didn't have the min/max MSRs.
Assume min=3.0x & max = whatever we booted at. */
...
...
@@ -416,17 +416,17 @@ static int __init longhaul_get_ranges (void)
break
;
case
2
...
3
:
rdmsr
(
MSR_VIA_LONGHAUL
,
lo
,
hi
);
rdmsr
l
(
MSR_VIA_LONGHAUL
,
longhaul
.
val
);
invalue
=
(
hi
&
(
1
<<
0
|
1
<<
1
|
1
<<
2
|
1
<<
3
))
;
if
(
hi
&
(
1
<<
11
)
)
invalue
=
longhaul
.
bits
.
MaxMHzBR
;
if
(
longhaul
.
bits
.
MaxMHzBR4
)
invalue
+=
16
;
maxmult
=
multipliers
[
invalue
];
#if 0
/* This is MaxMhz @ Min Voltage. Ignore for now */
invalue =
(hi & (1<<16|1<<17|1<<18|1<<19)) >> 16
;
if (
hi & (1<<27))
invalue += 16;
#if 0
invalue =
longhaul.bits.MinMHzBR
;
if (
longhaul.bits.MinMHzBR4);
invalue += 16;
minmult = multipliers[invalue];
#else
minmult
=
30
;
/* as per spec */
...
...
@@ -460,18 +460,23 @@ static int __init longhaul_get_ranges (void)
kfree
(
longhaul_table
);
return
-
EINVAL
;
}
return
0
;
}
static
void
__init
longhaul_setup_voltagescaling
(
unsigned
long
lo
,
unsigned
long
hi
)
static
void
__init
longhaul_setup_voltagescaling
(
void
)
{
int
revkey
;
union
msr_longhaul
longhaul
;
rdmsrl
(
MSR_VIA_LONGHAUL
,
longhaul
.
val
);
if
(
!
(
longhaul
.
bits
.
RevisionID
&
1
))
return
;
minvid
=
(
hi
&
(
1
<<
20
|
1
<<
21
|
1
<<
22
|
1
<<
23
|
1
<<
24
))
>>
20
;
/* 56:52 */
maxvid
=
(
hi
&
(
1
<<
4
|
1
<<
5
|
1
<<
6
|
1
<<
7
|
1
<<
8
))
>>
4
;
/* 40:36 */
vrmrev
=
(
lo
&
(
1
<<
15
))
>>
15
;
minvid
=
longhaul
.
bits
.
MinimumVID
;
maxvid
=
longhaul
.
bits
.
MaximumVID
;
vrmrev
=
longhaul
.
bits
.
VRMRev
;
if
(
minvid
==
0
||
maxvid
==
0
)
{
printk
(
KERN_INFO
PFX
"Bogus values Min:%d.%03d Max:%d.%03d. "
...
...
@@ -499,14 +504,14 @@ static void __init longhaul_setup_voltagescaling (unsigned long lo, unsigned lon
/* Current voltage isn't readable at first, so we need to
set it to a known value. The spec says to use maxvid */
revkey
=
(
lo
&
0xf
)
<<
4
;
/* Rev key. */
lo
|=
revkey
;
/* Reinsert key FIXME: This is bad. */
lo
&=
0xfe0fff0f
;
/* Mask unneeded bits */
lo
|=
(
1
<<
9
);
/* EnableSoftVID */
lo
|=
maxvid
<<
20
;
wrmsr
(
MSR_VIA_LONGHAUL
,
lo
,
hi
);
longhaul
.
bits
.
RevisionKey
=
longhaul
.
bits
.
RevisionID
;
/* FIXME: This is bad. */
longhaul
.
bits
.
EnableSoftVID
=
1
;
longhaul
.
bits
.
SoftVID
=
maxvid
;
wrmsrl
(
MSR_VIA_LONGHAUL
,
longhaul
.
val
);
minvid
=
voltage_table
[
minvid
];
maxvid
=
voltage_table
[
maxvid
];
dprintk
(
"Min VID=%d.%03d Max VID=%d.%03d, %d possible voltage scales
\n
"
,
maxvid
/
1000
,
maxvid
%
1000
,
minvid
/
1000
,
minvid
%
1000
,
numvscales
);
...
...
@@ -524,8 +529,8 @@ static int longhaul_target (struct cpufreq_policy *policy,
unsigned
int
target_freq
,
unsigned
int
relation
)
{
unsigned
int
table_index
=
0
;
unsigned
int
new_clock_ratio
=
0
;
unsigned
int
table_index
=
0
;
unsigned
int
new_clock_ratio
=
0
;
if
(
cpufreq_frequency_table_target
(
policy
,
longhaul_table
,
target_freq
,
relation
,
&
table_index
))
return
-
EINVAL
;
...
...
@@ -544,7 +549,7 @@ static int longhaul_cpu_init (struct cpufreq_policy *policy)
switch
(
c
->
x86_model
)
{
case
6
:
/* VIA C3 Samuel C5A */
longhaul
=
1
;
longhaul
_version
=
1
;
memcpy
(
clock_ratio
,
longhaul1_clock_ratio
,
sizeof
(
longhaul1_clock_ratio
));
memcpy
(
eblcr_table
,
samuel1_eblcr
,
sizeof
(
samuel1_eblcr
));
break
;
...
...
@@ -552,12 +557,12 @@ static int longhaul_cpu_init (struct cpufreq_policy *policy)
case
7
:
/* C5B / C5C */
switch
(
c
->
x86_mask
)
{
case
0
:
longhaul
=
1
;
longhaul
_version
=
1
;
memcpy
(
clock_ratio
,
longhaul1_clock_ratio
,
sizeof
(
longhaul1_clock_ratio
));
memcpy
(
eblcr_table
,
samuel2_eblcr
,
sizeof
(
samuel2_eblcr
));
break
;
case
1
...
15
:
longhaul
=
2
;
longhaul
_version
=
2
;
memcpy
(
clock_ratio
,
longhaul2_clock_ratio
,
sizeof
(
longhaul2_clock_ratio
));
memcpy
(
eblcr_table
,
ezra_eblcr
,
sizeof
(
ezra_eblcr
));
break
;
...
...
@@ -566,21 +571,18 @@ static int longhaul_cpu_init (struct cpufreq_policy *policy)
case
8
:
/* C5M/C5N */
return
-
ENODEV
;
// Waiting on updated docs from VIA before this is usable
longhaul
=
3
;
longhaul
_version
=
3
;
numscales
=
32
;
memcpy
(
clock_ratio
,
longhaul3_clock_ratio
,
sizeof
(
longhaul3_clock_ratio
));
memcpy
(
eblcr_table
,
c5m_eblcr
,
sizeof
(
c5m_eblcr
));
break
;
}
printk
(
KERN_INFO
PFX
"VIA CPU detected. Longhaul version %d supported
\n
"
,
longhaul
);
printk
(
KERN_INFO
PFX
"VIA CPU detected. Longhaul version %d supported
\n
"
,
longhaul_version
);
if
(
longhaul
==
2
||
longhaul
==
3
)
{
unsigned
long
lo
,
hi
;
rdmsr
(
MSR_VIA_LONGHAUL
,
lo
,
hi
);
if
((
lo
&
(
1
<<
0
))
&&
(
dont_scale_voltage
==
0
))
longhaul_setup_voltagescaling
(
lo
,
hi
);
}
if
((
longhaul_version
==
2
||
longhaul_version
==
3
)
&&
(
dont_scale_voltage
==
0
))
longhaul_setup_voltagescaling
();
ret
=
longhaul_get_ranges
();
if
(
ret
!=
0
)
...
...
arch/i386/kernel/cpu/cpufreq/longhaul.h
0 → 100644
View file @
94db5ad4
/*
* longhaul.h
* (C) 2003 Dave Jones.
*
* Licensed under the terms of the GNU GPL License version 2.
*
* VIA-specific information
*/
union
msr_longhaul
{
struct
{
unsigned
RevisionID
:
4
,
// 3:0
RevisionKey:
4
,
// 7:4
EnableSoftBusRatio:
1
,
// 8
EnableSoftVID:
1
,
// 9
EnableSoftBSEL:
1
,
// 10
Reserved:
3
,
// 11:13
SoftBusRatio4:
1
,
// 14
VRMRev:
1
,
// 15
SoftBusRatio:
4
,
// 19:16
SoftVID:
5
,
// 24:20
Reserved2:
3
,
// 27:25
SoftBSEL:
2
,
// 29:28
Reserved3:
2
,
// 31:30
MaxMHzBR:
4
,
// 35:32
MaximumVID:
5
,
// 40:36
MaxMHzFSB:
2
,
// 42:41
MaxMHzBR4:
1
,
// 43
Reserved4:
4
,
// 47:44
MinMHzBR:
4
,
// 51:48
MinimumVID:
5
,
// 56:52
MinMHzFSB:
2
,
// 58:57
MinMHzBR4:
1
,
// 59
Reserved5:
4
;
// 63:60
}
bits
;
unsigned
long
long
val
;
};
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