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
e8684605
Commit
e8684605
authored
Mar 26, 2009
by
Ingo Molnar
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'timers/hpet' into timers/core
parents
a5ebc0b1
c23e253e
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
67 additions
and
17 deletions
+67
-17
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+3
-1
arch/x86/kernel/hpet.c
arch/x86/kernel/hpet.c
+64
-16
No files found.
Documentation/kernel-parameters.txt
View file @
e8684605
...
@@ -492,10 +492,12 @@ and is between 256 and 4096 characters. It is defined in the file
...
@@ -492,10 +492,12 @@ and is between 256 and 4096 characters. It is defined in the file
Default: 64
Default: 64
hpet= [X86-32,HPET] option to control HPET usage
hpet= [X86-32,HPET] option to control HPET usage
Format: { enable (default) | disable | force }
Format: { enable (default) | disable | force |
verbose }
disable: disable HPET and use PIT instead
disable: disable HPET and use PIT instead
force: allow force enabled of undocumented chips (ICH4,
force: allow force enabled of undocumented chips (ICH4,
VIA, nVidia)
VIA, nVidia)
verbose: show contents of HPET registers during setup
com20020= [HW,NET] ARCnet - COM20020 chipset
com20020= [HW,NET] ARCnet - COM20020 chipset
Format:
Format:
...
...
arch/x86/kernel/hpet.c
View file @
e8684605
...
@@ -80,6 +80,7 @@ static inline void hpet_clear_mapping(void)
...
@@ -80,6 +80,7 @@ static inline void hpet_clear_mapping(void)
*/
*/
static
int
boot_hpet_disable
;
static
int
boot_hpet_disable
;
int
hpet_force_user
;
int
hpet_force_user
;
static
int
hpet_verbose
;
static
int
__init
hpet_setup
(
char
*
str
)
static
int
__init
hpet_setup
(
char
*
str
)
{
{
...
@@ -88,6 +89,8 @@ static int __init hpet_setup(char *str)
...
@@ -88,6 +89,8 @@ static int __init hpet_setup(char *str)
boot_hpet_disable
=
1
;
boot_hpet_disable
=
1
;
if
(
!
strncmp
(
"force"
,
str
,
5
))
if
(
!
strncmp
(
"force"
,
str
,
5
))
hpet_force_user
=
1
;
hpet_force_user
=
1
;
if
(
!
strncmp
(
"verbose"
,
str
,
7
))
hpet_verbose
=
1
;
}
}
return
1
;
return
1
;
}
}
...
@@ -119,6 +122,43 @@ int is_hpet_enabled(void)
...
@@ -119,6 +122,43 @@ int is_hpet_enabled(void)
}
}
EXPORT_SYMBOL_GPL
(
is_hpet_enabled
);
EXPORT_SYMBOL_GPL
(
is_hpet_enabled
);
static
void
_hpet_print_config
(
const
char
*
function
,
int
line
)
{
u32
i
,
timers
,
l
,
h
;
printk
(
KERN_INFO
"hpet: %s(%d):
\n
"
,
function
,
line
);
l
=
hpet_readl
(
HPET_ID
);
h
=
hpet_readl
(
HPET_PERIOD
);
timers
=
((
l
&
HPET_ID_NUMBER
)
>>
HPET_ID_NUMBER_SHIFT
)
+
1
;
printk
(
KERN_INFO
"hpet: ID: 0x%x, PERIOD: 0x%x
\n
"
,
l
,
h
);
l
=
hpet_readl
(
HPET_CFG
);
h
=
hpet_readl
(
HPET_STATUS
);
printk
(
KERN_INFO
"hpet: CFG: 0x%x, STATUS: 0x%x
\n
"
,
l
,
h
);
l
=
hpet_readl
(
HPET_COUNTER
);
h
=
hpet_readl
(
HPET_COUNTER
+
4
);
printk
(
KERN_INFO
"hpet: COUNTER_l: 0x%x, COUNTER_h: 0x%x
\n
"
,
l
,
h
);
for
(
i
=
0
;
i
<
timers
;
i
++
)
{
l
=
hpet_readl
(
HPET_Tn_CFG
(
i
));
h
=
hpet_readl
(
HPET_Tn_CFG
(
i
)
+
4
);
printk
(
KERN_INFO
"hpet: T%d: CFG_l: 0x%x, CFG_h: 0x%x
\n
"
,
i
,
l
,
h
);
l
=
hpet_readl
(
HPET_Tn_CMP
(
i
));
h
=
hpet_readl
(
HPET_Tn_CMP
(
i
)
+
4
);
printk
(
KERN_INFO
"hpet: T%d: CMP_l: 0x%x, CMP_h: 0x%x
\n
"
,
i
,
l
,
h
);
l
=
hpet_readl
(
HPET_Tn_ROUTE
(
i
));
h
=
hpet_readl
(
HPET_Tn_ROUTE
(
i
)
+
4
);
printk
(
KERN_INFO
"hpet: T%d ROUTE_l: 0x%x, ROUTE_h: 0x%x
\n
"
,
i
,
l
,
h
);
}
}
#define hpet_print_config() \
do { \
if (hpet_verbose) \
_hpet_print_config(__FUNCTION__, __LINE__); \
} while (0)
/*
/*
* When the hpet driver (/dev/hpet) is enabled, we need to reserve
* When the hpet driver (/dev/hpet) is enabled, we need to reserve
* timer 0 and timer 1 in case of RTC emulation.
* timer 0 and timer 1 in case of RTC emulation.
...
@@ -191,27 +231,37 @@ static struct clock_event_device hpet_clockevent = {
...
@@ -191,27 +231,37 @@ static struct clock_event_device hpet_clockevent = {
.
rating
=
50
,
.
rating
=
50
,
};
};
static
void
hpet_st
art
_counter
(
void
)
static
void
hpet_st
op
_counter
(
void
)
{
{
unsigned
long
cfg
=
hpet_readl
(
HPET_CFG
);
unsigned
long
cfg
=
hpet_readl
(
HPET_CFG
);
cfg
&=
~
HPET_CFG_ENABLE
;
cfg
&=
~
HPET_CFG_ENABLE
;
hpet_writel
(
cfg
,
HPET_CFG
);
hpet_writel
(
cfg
,
HPET_CFG
);
hpet_writel
(
0
,
HPET_COUNTER
);
hpet_writel
(
0
,
HPET_COUNTER
);
hpet_writel
(
0
,
HPET_COUNTER
+
4
);
hpet_writel
(
0
,
HPET_COUNTER
+
4
);
}
static
void
hpet_start_counter
(
void
)
{
unsigned
long
cfg
=
hpet_readl
(
HPET_CFG
);
cfg
|=
HPET_CFG_ENABLE
;
cfg
|=
HPET_CFG_ENABLE
;
hpet_writel
(
cfg
,
HPET_CFG
);
hpet_writel
(
cfg
,
HPET_CFG
);
}
}
static
void
hpet_restart_counter
(
void
)
{
hpet_stop_counter
();
hpet_start_counter
();
}
static
void
hpet_resume_device
(
void
)
static
void
hpet_resume_device
(
void
)
{
{
force_hpet_resume
();
force_hpet_resume
();
}
}
static
void
hpet_res
tart
_counter
(
void
)
static
void
hpet_res
ume
_counter
(
void
)
{
{
hpet_resume_device
();
hpet_resume_device
();
hpet_start_counter
();
hpet_
re
start_counter
();
}
}
static
void
hpet_enable_legacy_int
(
void
)
static
void
hpet_enable_legacy_int
(
void
)
...
@@ -259,29 +309,23 @@ static int hpet_setup_msi_irq(unsigned int irq);
...
@@ -259,29 +309,23 @@ static int hpet_setup_msi_irq(unsigned int irq);
static
void
hpet_set_mode
(
enum
clock_event_mode
mode
,
static
void
hpet_set_mode
(
enum
clock_event_mode
mode
,
struct
clock_event_device
*
evt
,
int
timer
)
struct
clock_event_device
*
evt
,
int
timer
)
{
{
unsigned
long
cfg
,
cmp
,
now
;
unsigned
long
cfg
;
uint64_t
delta
;
uint64_t
delta
;
switch
(
mode
)
{
switch
(
mode
)
{
case
CLOCK_EVT_MODE_PERIODIC
:
case
CLOCK_EVT_MODE_PERIODIC
:
hpet_stop_counter
();
delta
=
((
uint64_t
)(
NSEC_PER_SEC
/
HZ
))
*
evt
->
mult
;
delta
=
((
uint64_t
)(
NSEC_PER_SEC
/
HZ
))
*
evt
->
mult
;
delta
>>=
evt
->
shift
;
delta
>>=
evt
->
shift
;
now
=
hpet_readl
(
HPET_COUNTER
);
cmp
=
now
+
(
unsigned
long
)
delta
;
cfg
=
hpet_readl
(
HPET_Tn_CFG
(
timer
));
cfg
=
hpet_readl
(
HPET_Tn_CFG
(
timer
));
/* Make sure we use edge triggered interrupts */
/* Make sure we use edge triggered interrupts */
cfg
&=
~
HPET_TN_LEVEL
;
cfg
&=
~
HPET_TN_LEVEL
;
cfg
|=
HPET_TN_ENABLE
|
HPET_TN_PERIODIC
|
cfg
|=
HPET_TN_ENABLE
|
HPET_TN_PERIODIC
|
HPET_TN_SETVAL
|
HPET_TN_32BIT
;
HPET_TN_SETVAL
|
HPET_TN_32BIT
;
hpet_writel
(
cfg
,
HPET_Tn_CFG
(
timer
));
hpet_writel
(
cfg
,
HPET_Tn_CFG
(
timer
));
/*
* The first write after writing TN_SETVAL to the
* config register sets the counter value, the second
* write sets the period.
*/
hpet_writel
(
cmp
,
HPET_Tn_CMP
(
timer
));
udelay
(
1
);
hpet_writel
((
unsigned
long
)
delta
,
HPET_Tn_CMP
(
timer
));
hpet_writel
((
unsigned
long
)
delta
,
HPET_Tn_CMP
(
timer
));
hpet_start_counter
();
hpet_print_config
();
break
;
break
;
case
CLOCK_EVT_MODE_ONESHOT
:
case
CLOCK_EVT_MODE_ONESHOT
:
...
@@ -308,6 +352,7 @@ static void hpet_set_mode(enum clock_event_mode mode,
...
@@ -308,6 +352,7 @@ static void hpet_set_mode(enum clock_event_mode mode,
irq_set_affinity
(
hdev
->
irq
,
cpumask_of
(
hdev
->
cpu
));
irq_set_affinity
(
hdev
->
irq
,
cpumask_of
(
hdev
->
cpu
));
enable_irq
(
hdev
->
irq
);
enable_irq
(
hdev
->
irq
);
}
}
hpet_print_config
();
break
;
break
;
}
}
}
}
...
@@ -526,6 +571,7 @@ static void hpet_msi_capability_lookup(unsigned int start_timer)
...
@@ -526,6 +571,7 @@ static void hpet_msi_capability_lookup(unsigned int start_timer)
num_timers
=
((
id
&
HPET_ID_NUMBER
)
>>
HPET_ID_NUMBER_SHIFT
);
num_timers
=
((
id
&
HPET_ID_NUMBER
)
>>
HPET_ID_NUMBER_SHIFT
);
num_timers
++
;
/* Value read out starts from 0 */
num_timers
++
;
/* Value read out starts from 0 */
hpet_print_config
();
hpet_devs
=
kzalloc
(
sizeof
(
struct
hpet_dev
)
*
num_timers
,
GFP_KERNEL
);
hpet_devs
=
kzalloc
(
sizeof
(
struct
hpet_dev
)
*
num_timers
,
GFP_KERNEL
);
if
(
!
hpet_devs
)
if
(
!
hpet_devs
)
...
@@ -695,7 +741,7 @@ static struct clocksource clocksource_hpet = {
...
@@ -695,7 +741,7 @@ static struct clocksource clocksource_hpet = {
.
mask
=
HPET_MASK
,
.
mask
=
HPET_MASK
,
.
shift
=
HPET_SHIFT
,
.
shift
=
HPET_SHIFT
,
.
flags
=
CLOCK_SOURCE_IS_CONTINUOUS
,
.
flags
=
CLOCK_SOURCE_IS_CONTINUOUS
,
.
resume
=
hpet_res
tart
_counter
,
.
resume
=
hpet_res
ume
_counter
,
#ifdef CONFIG_X86_64
#ifdef CONFIG_X86_64
.
vread
=
vread_hpet
,
.
vread
=
vread_hpet
,
#endif
#endif
...
@@ -707,7 +753,7 @@ static int hpet_clocksource_register(void)
...
@@ -707,7 +753,7 @@ static int hpet_clocksource_register(void)
cycle_t
t1
;
cycle_t
t1
;
/* Start the counter */
/* Start the counter */
hpet_start_counter
();
hpet_
re
start_counter
();
/* Verify whether hpet counter works */
/* Verify whether hpet counter works */
t1
=
read_hpet
();
t1
=
read_hpet
();
...
@@ -793,6 +839,7 @@ int __init hpet_enable(void)
...
@@ -793,6 +839,7 @@ int __init hpet_enable(void)
* information and the number of channels
* information and the number of channels
*/
*/
id
=
hpet_readl
(
HPET_ID
);
id
=
hpet_readl
(
HPET_ID
);
hpet_print_config
();
#ifdef CONFIG_HPET_EMULATE_RTC
#ifdef CONFIG_HPET_EMULATE_RTC
/*
/*
...
@@ -845,6 +892,7 @@ static __init int hpet_late_init(void)
...
@@ -845,6 +892,7 @@ static __init int hpet_late_init(void)
return
-
ENODEV
;
return
-
ENODEV
;
hpet_reserve_platform_timers
(
hpet_readl
(
HPET_ID
));
hpet_reserve_platform_timers
(
hpet_readl
(
HPET_ID
));
hpet_print_config
();
for_each_online_cpu
(
cpu
)
{
for_each_online_cpu
(
cpu
)
{
hpet_cpuhp_notify
(
NULL
,
CPU_ONLINE
,
(
void
*
)(
long
)
cpu
);
hpet_cpuhp_notify
(
NULL
,
CPU_ONLINE
,
(
void
*
)(
long
)
cpu
);
...
...
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