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
7bcf7717
Commit
7bcf7717
authored
Oct 11, 2007
by
Ralf Baechle
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[MIPS] Implement clockevents for R4000-style cp0 count/compare interrupt
Signed-off-by:
Ralf Baechle
<
ralf@linux-mips.org
>
parent
91a2fcc8
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
210 additions
and
200 deletions
+210
-200
arch/mips/Kconfig
arch/mips/Kconfig
+7
-0
arch/mips/au1000/common/irq.c
arch/mips/au1000/common/irq.c
+1
-1
arch/mips/configs/bigsur_defconfig
arch/mips/configs/bigsur_defconfig
+0
-1
arch/mips/configs/sb1250-swarm_defconfig
arch/mips/configs/sb1250-swarm_defconfig
+0
-1
arch/mips/kernel/process.c
arch/mips/kernel/process.c
+3
-0
arch/mips/kernel/smp.c
arch/mips/kernel/smp.c
+2
-0
arch/mips/kernel/smtc.c
arch/mips/kernel/smtc.c
+1
-1
arch/mips/kernel/time.c
arch/mips/kernel/time.c
+118
-138
arch/mips/mips-boards/generic/time.c
arch/mips/mips-boards/generic/time.c
+10
-16
arch/mips/qemu/q-irq.c
arch/mips/qemu/q-irq.c
+3
-1
arch/mips/qemu/q-setup.c
arch/mips/qemu/q-setup.c
+0
-1
arch/mips/sgi-ip22/ip22-int.c
arch/mips/sgi-ip22/ip22-int.c
+1
-1
arch/mips/sgi-ip32/ip32-irq.c
arch/mips/sgi-ip32/ip32-irq.c
+1
-1
arch/mips/sibyte/Kconfig
arch/mips/sibyte/Kconfig
+8
-4
arch/mips/sibyte/bcm1480/irq.c
arch/mips/sibyte/bcm1480/irq.c
+10
-3
arch/mips/sibyte/sb1250/irq.c
arch/mips/sibyte/sb1250/irq.c
+37
-13
arch/mips/sibyte/sb1250/time.c
arch/mips/sibyte/sb1250/time.c
+0
-12
include/asm-mips/mach-ip27/irq.h
include/asm-mips/mach-ip27/irq.h
+2
-0
include/asm-mips/qemu.h
include/asm-mips/qemu.h
+1
-1
include/asm-mips/time.h
include/asm-mips/time.h
+5
-5
No files found.
arch/mips/Kconfig
View file @
7bcf7717
...
@@ -335,6 +335,7 @@ config QEMU
...
@@ -335,6 +335,7 @@ config QEMU
select GENERIC_ISA_DMA
select GENERIC_ISA_DMA
select HAVE_STD_PC_SERIAL_PORT
select HAVE_STD_PC_SERIAL_PORT
select I8259
select I8259
select IRQ_CPU
select ISA
select ISA
select PCSPEAKER
select PCSPEAKER
select SWAP_IO_SPACE
select SWAP_IO_SPACE
...
@@ -667,6 +668,10 @@ config GENERIC_CALIBRATE_DELAY
...
@@ -667,6 +668,10 @@ config GENERIC_CALIBRATE_DELAY
bool
bool
default y
default y
config GENERIC_CLOCKEVENTS
bool
default y
config GENERIC_TIME
config GENERIC_TIME
bool
bool
default y
default y
...
@@ -901,6 +906,8 @@ config BOOT_ELF64
...
@@ -901,6 +906,8 @@ config BOOT_ELF64
menu "CPU selection"
menu "CPU selection"
source "kernel/time/Kconfig"
choice
choice
prompt "CPU type"
prompt "CPU type"
default CPU_R4X00
default CPU_R4X00
...
...
arch/mips/au1000/common/irq.c
View file @
7bcf7717
...
@@ -633,7 +633,7 @@ asmlinkage void plat_irq_dispatch(void)
...
@@ -633,7 +633,7 @@ asmlinkage void plat_irq_dispatch(void)
unsigned
int
pending
=
read_c0_status
()
&
read_c0_cause
()
&
ST0_IM
;
unsigned
int
pending
=
read_c0_status
()
&
read_c0_cause
()
&
ST0_IM
;
if
(
pending
&
CAUSEF_IP7
)
if
(
pending
&
CAUSEF_IP7
)
ll_timer_interrupt
(
63
);
do_IRQ
(
63
);
else
if
(
pending
&
CAUSEF_IP2
)
else
if
(
pending
&
CAUSEF_IP2
)
intc0_req0_irqdispatch
();
intc0_req0_irqdispatch
();
else
if
(
pending
&
CAUSEF_IP3
)
else
if
(
pending
&
CAUSEF_IP3
)
...
...
arch/mips/configs/bigsur_defconfig
View file @
7bcf7717
...
@@ -69,7 +69,6 @@ CONFIG_SIBYTE_SB1xxx_SOC=y
...
@@ -69,7 +69,6 @@ CONFIG_SIBYTE_SB1xxx_SOC=y
CONFIG_SIBYTE_CFE=y
CONFIG_SIBYTE_CFE=y
# CONFIG_SIBYTE_CFE_CONSOLE is not set
# CONFIG_SIBYTE_CFE_CONSOLE is not set
# CONFIG_SIBYTE_BUS_WATCHER is not set
# CONFIG_SIBYTE_BUS_WATCHER is not set
# CONFIG_SIBYTE_SB1250_PROF is not set
# CONFIG_SIBYTE_TBPROF is not set
# CONFIG_SIBYTE_TBPROF is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
...
...
arch/mips/configs/sb1250-swarm_defconfig
View file @
7bcf7717
...
@@ -70,7 +70,6 @@ CONFIG_SIBYTE_HAS_LDT=y
...
@@ -70,7 +70,6 @@ CONFIG_SIBYTE_HAS_LDT=y
CONFIG_SIBYTE_CFE=y
CONFIG_SIBYTE_CFE=y
# CONFIG_SIBYTE_CFE_CONSOLE is not set
# CONFIG_SIBYTE_CFE_CONSOLE is not set
# CONFIG_SIBYTE_BUS_WATCHER is not set
# CONFIG_SIBYTE_BUS_WATCHER is not set
# CONFIG_SIBYTE_SB1250_PROF is not set
# CONFIG_SIBYTE_TBPROF is not set
# CONFIG_SIBYTE_TBPROF is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
...
...
arch/mips/kernel/process.c
View file @
7bcf7717
...
@@ -11,6 +11,7 @@
...
@@ -11,6 +11,7 @@
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/tick.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/stddef.h>
...
@@ -52,6 +53,7 @@ void __noreturn cpu_idle(void)
...
@@ -52,6 +53,7 @@ void __noreturn cpu_idle(void)
{
{
/* endless idle loop with no priority at all */
/* endless idle loop with no priority at all */
while
(
1
)
{
while
(
1
)
{
tick_nohz_stop_sched_tick
();
while
(
!
need_resched
())
{
while
(
!
need_resched
())
{
#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
extern
void
smtc_idle_loop_hook
(
void
);
extern
void
smtc_idle_loop_hook
(
void
);
...
@@ -61,6 +63,7 @@ void __noreturn cpu_idle(void)
...
@@ -61,6 +63,7 @@ void __noreturn cpu_idle(void)
if
(
cpu_wait
)
if
(
cpu_wait
)
(
*
cpu_wait
)();
(
*
cpu_wait
)();
}
}
tick_nohz_restart_sched_tick
();
preempt_enable_no_resched
();
preempt_enable_no_resched
();
schedule
();
schedule
();
preempt_disable
();
preempt_disable
();
...
...
arch/mips/kernel/smp.c
View file @
7bcf7717
...
@@ -38,6 +38,7 @@
...
@@ -38,6 +38,7 @@
#include <asm/system.h>
#include <asm/system.h>
#include <asm/mmu_context.h>
#include <asm/mmu_context.h>
#include <asm/smp.h>
#include <asm/smp.h>
#include <asm/time.h>
#ifdef CONFIG_MIPS_MT_SMTC
#ifdef CONFIG_MIPS_MT_SMTC
#include <asm/mipsmtregs.h>
#include <asm/mipsmtregs.h>
...
@@ -70,6 +71,7 @@ asmlinkage __cpuinit void start_secondary(void)
...
@@ -70,6 +71,7 @@ asmlinkage __cpuinit void start_secondary(void)
cpu_probe
();
cpu_probe
();
cpu_report
();
cpu_report
();
per_cpu_trap_init
();
per_cpu_trap_init
();
mips_clockevent_init
();
prom_init_secondary
();
prom_init_secondary
();
/*
/*
...
...
arch/mips/kernel/smtc.c
View file @
7bcf7717
...
@@ -867,7 +867,7 @@ void ipi_decode(struct smtc_ipi *pipi)
...
@@ -867,7 +867,7 @@ void ipi_decode(struct smtc_ipi *pipi)
#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
clock_hang_reported
[
dest_copy
]
=
0
;
clock_hang_reported
[
dest_copy
]
=
0
;
#endif
/* CONFIG_SMTC_IDLE_HOOK_DEBUG */
#endif
/* CONFIG_SMTC_IDLE_HOOK_DEBUG */
local_timer_interrupt
(
0
);
local_timer_interrupt
(
0
,
NULL
);
irq_exit
();
irq_exit
();
break
;
break
;
case
LINUX_SMP_IPI
:
case
LINUX_SMP_IPI
:
...
...
arch/mips/kernel/time.c
View file @
7bcf7717
...
@@ -11,6 +11,7 @@
...
@@ -11,6 +11,7 @@
* Free Software Foundation; either version 2 of the License, or (at your
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
* option) any later version.
*/
*/
#include <linux/clockchips.h>
#include <linux/types.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/init.h>
...
@@ -34,6 +35,8 @@
...
@@ -34,6 +35,8 @@
#include <asm/sections.h>
#include <asm/sections.h>
#include <asm/time.h>
#include <asm/time.h>
#include <irq.h>
/*
/*
* The integer part of the number of usecs per jiffy is taken from tick,
* The integer part of the number of usecs per jiffy is taken from tick,
* but the fractional part is not recorded, so we calculate it using the
* but the fractional part is not recorded, so we calculate it using the
...
@@ -70,10 +73,6 @@ int update_persistent_clock(struct timespec now)
...
@@ -70,10 +73,6 @@ int update_persistent_clock(struct timespec now)
/* how many counter cycles in a jiffy */
/* how many counter cycles in a jiffy */
static
unsigned
long
cycles_per_jiffy
__read_mostly
;
static
unsigned
long
cycles_per_jiffy
__read_mostly
;
/* expirelo is the count value for next CPU timer interrupt */
static
unsigned
int
expirelo
;
/*
/*
* Null timer ack for systems not needing one (e.g. i8254).
* Null timer ack for systems not needing one (e.g. i8254).
*/
*/
...
@@ -92,18 +91,7 @@ static cycle_t null_hpt_read(void)
...
@@ -92,18 +91,7 @@ static cycle_t null_hpt_read(void)
*/
*/
static
void
c0_timer_ack
(
void
)
static
void
c0_timer_ack
(
void
)
{
{
unsigned
int
count
;
write_c0_compare
(
read_c0_compare
());
/* Ack this timer interrupt and set the next one. */
expirelo
+=
cycles_per_jiffy
;
write_c0_compare
(
expirelo
);
/* Check to see if we have missed any timer interrupts. */
while
(((
count
=
read_c0_count
())
-
expirelo
)
<
0x7fffffff
)
{
/* missed_timer_count++; */
expirelo
=
count
+
cycles_per_jiffy
;
write_c0_compare
(
expirelo
);
}
}
}
/*
/*
...
@@ -114,13 +102,6 @@ static cycle_t c0_hpt_read(void)
...
@@ -114,13 +102,6 @@ static cycle_t c0_hpt_read(void)
return
read_c0_count
();
return
read_c0_count
();
}
}
/* For use both as a high precision timer and an interrupt source. */
static
void
__init
c0_hpt_timer_init
(
void
)
{
expirelo
=
read_c0_count
()
+
cycles_per_jiffy
;
write_c0_compare
(
expirelo
);
}
int
(
*
mips_timer_state
)(
void
);
int
(
*
mips_timer_state
)(
void
);
void
(
*
mips_timer_ack
)(
void
);
void
(
*
mips_timer_ack
)(
void
);
...
@@ -140,35 +121,6 @@ void local_timer_interrupt(int irq, void *dev_id)
...
@@ -140,35 +121,6 @@ void local_timer_interrupt(int irq, void *dev_id)
update_process_times
(
user_mode
(
get_irq_regs
()));
update_process_times
(
user_mode
(
get_irq_regs
()));
}
}
/*
* High-level timer interrupt service routines. This function
* is set as irqaction->handler and is invoked through do_IRQ.
*/
static
irqreturn_t
timer_interrupt
(
int
irq
,
void
*
dev_id
)
{
write_seqlock
(
&
xtime_lock
);
mips_timer_ack
();
/*
* call the generic timer interrupt handling
*/
do_timer
(
1
);
write_sequnlock
(
&
xtime_lock
);
/*
* In UP mode, we call local_timer_interrupt() to do profiling
* and process accouting.
*
* In SMP mode, local_timer_interrupt() is invoked by appropriate
* low-level local timer interrupt handler.
*/
local_timer_interrupt
(
irq
,
dev_id
);
return
IRQ_HANDLED
;
}
int
null_perf_irq
(
void
)
int
null_perf_irq
(
void
)
{
{
return
0
;
return
0
;
...
@@ -209,81 +161,6 @@ static inline int handle_perf_irq (int r2)
...
@@ -209,81 +161,6 @@ static inline int handle_perf_irq (int r2)
!
r2
;
!
r2
;
}
}
void
ll_timer_interrupt
(
int
irq
,
void
*
dev_id
)
{
int
cpu
=
smp_processor_id
();
#ifdef CONFIG_MIPS_MT_SMTC
/*
* In an SMTC system, one Count/Compare set exists per VPE.
* Which TC within a VPE gets the interrupt is essentially
* random - we only know that it shouldn't be one with
* IXMT set. Whichever TC gets the interrupt needs to
* send special interprocessor interrupts to the other
* TCs to make sure that they schedule, etc.
*
* That code is specific to the SMTC kernel, not to
* the a particular platform, so it's invoked from
* the general MIPS timer_interrupt routine.
*/
/*
* We could be here due to timer interrupt,
* perf counter overflow, or both.
*/
(
void
)
handle_perf_irq
(
1
);
if
(
read_c0_cause
()
&
(
1
<<
30
))
{
/*
* There are things we only want to do once per tick
* in an "MP" system. One TC of each VPE will take
* the actual timer interrupt. The others will get
* timer broadcast IPIs. We use whoever it is that takes
* the tick on VPE 0 to run the full timer_interrupt().
*/
if
(
cpu_data
[
cpu
].
vpe_id
==
0
)
{
timer_interrupt
(
irq
,
NULL
);
}
else
{
write_c0_compare
(
read_c0_count
()
+
(
mips_hpt_frequency
/
HZ
));
local_timer_interrupt
(
irq
,
dev_id
);
}
smtc_timer_broadcast
(
cpu_data
[
cpu
].
vpe_id
);
}
#else
/* CONFIG_MIPS_MT_SMTC */
int
r2
=
cpu_has_mips_r2
;
if
(
handle_perf_irq
(
r2
))
return
;
if
(
r2
&&
((
read_c0_cause
()
&
(
1
<<
30
))
==
0
))
return
;
if
(
cpu
==
0
)
{
/*
* CPU 0 handles the global timer interrupt job and process
* accounting resets count/compare registers to trigger next
* timer int.
*/
timer_interrupt
(
irq
,
NULL
);
}
else
{
/* Everyone else needs to reset the timer int here as
ll_local_timer_interrupt doesn't */
/*
* FIXME: need to cope with counter underflow.
* More support needs to be added to kernel/time for
* counter/timer interrupts on multiple CPU's
*/
write_c0_compare
(
read_c0_count
()
+
(
mips_hpt_frequency
/
HZ
));
/*
* Other CPUs should do profiling and process accounting
*/
local_timer_interrupt
(
irq
,
dev_id
);
}
#endif
/* CONFIG_MIPS_MT_SMTC */
}
/*
/*
* time_init() - it does the following things.
* time_init() - it does the following things.
*
*
...
@@ -301,12 +178,6 @@ void ll_timer_interrupt(int irq, void *dev_id)
...
@@ -301,12 +178,6 @@ void ll_timer_interrupt(int irq, void *dev_id)
unsigned
int
mips_hpt_frequency
;
unsigned
int
mips_hpt_frequency
;
static
struct
irqaction
timer_irqaction
=
{
.
handler
=
timer_interrupt
,
.
flags
=
IRQF_DISABLED
|
IRQF_PERCPU
,
.
name
=
"timer"
,
};
static
unsigned
int
__init
calibrate_hpt
(
void
)
static
unsigned
int
__init
calibrate_hpt
(
void
)
{
{
cycle_t
frequency
,
hpt_start
,
hpt_end
,
hpt_count
,
hz
;
cycle_t
frequency
,
hpt_start
,
hpt_end
,
hpt_count
,
hz
;
...
@@ -355,6 +226,65 @@ struct clocksource clocksource_mips = {
...
@@ -355,6 +226,65 @@ struct clocksource clocksource_mips = {
.
flags
=
CLOCK_SOURCE_IS_CONTINUOUS
,
.
flags
=
CLOCK_SOURCE_IS_CONTINUOUS
,
};
};
static
int
mips_next_event
(
unsigned
long
delta
,
struct
clock_event_device
*
evt
)
{
unsigned
int
cnt
;
cnt
=
read_c0_count
();
cnt
+=
delta
;
write_c0_compare
(
cnt
);
return
((
long
)(
read_c0_count
()
-
cnt
)
>
0
)
?
-
ETIME
:
0
;
}
static
void
mips_set_mode
(
enum
clock_event_mode
mode
,
struct
clock_event_device
*
evt
)
{
/* Nothing to do ... */
}
struct
clock_event_device
mips_clockevent
;
static
struct
clock_event_device
*
global_cd
[
NR_CPUS
];
static
int
cp0_timer_irq_installed
;
static
irqreturn_t
timer_interrupt
(
int
irq
,
void
*
dev_id
)
{
const
int
r2
=
cpu_has_mips_r2
;
struct
clock_event_device
*
cd
;
int
cpu
=
smp_processor_id
();
/*
* Suckage alert:
* Before R2 of the architecture there was no way to see if a
* performance counter interrupt was pending, so we have to run
* the performance counter interrupt handler anyway.
*/
if
(
handle_perf_irq
(
r2
))
goto
out
;
/*
* The same applies to performance counter interrupts. But with the
* above we now know that the reason we got here must be a timer
* interrupt. Being the paranoiacs we are we check anyway.
*/
if
(
!
r2
||
(
read_c0_cause
()
&
(
1
<<
30
)))
{
c0_timer_ack
();
cd
=
global_cd
[
cpu
];
cd
->
event_handler
(
cd
);
}
out:
return
IRQ_HANDLED
;
}
static
struct
irqaction
timer_irqaction
=
{
.
handler
=
timer_interrupt
,
.
flags
=
IRQF_DISABLED
|
IRQF_PERCPU
,
.
name
=
"timer"
,
};
static
void
__init
init_mips_clocksource
(
void
)
static
void
__init
init_mips_clocksource
(
void
)
{
{
u64
temp
;
u64
temp
;
...
@@ -382,6 +312,56 @@ void __init __weak plat_time_init(void)
...
@@ -382,6 +312,56 @@ void __init __weak plat_time_init(void)
{
{
}
}
void
__init
__weak
plat_timer_setup
(
struct
irqaction
*
irq
)
{
}
void
__cpuinit
mips_clockevent_init
(
void
)
{
uint64_t
mips_freq
=
mips_hpt_frequency
;
unsigned
int
cpu
=
smp_processor_id
();
struct
clock_event_device
*
cd
;
unsigned
int
irq
=
MIPS_CPU_IRQ_BASE
+
7
;
if
(
!
cpu_has_counter
)
return
;
if
(
cpu
==
0
)
cd
=
&
mips_clockevent
;
else
cd
=
kzalloc
(
sizeof
(
*
cd
),
GFP_ATOMIC
);
if
(
!
cd
)
return
;
/* We're probably roadkill ... */
cd
->
name
=
"MIPS"
;
cd
->
features
=
CLOCK_EVT_FEAT_ONESHOT
;
/* Calculate the min / max delta */
cd
->
mult
=
div_sc
((
unsigned
long
)
mips_freq
,
NSEC_PER_SEC
,
32
);
cd
->
shift
=
32
;
cd
->
max_delta_ns
=
clockevent_delta2ns
(
0x7fffffff
,
cd
);
cd
->
min_delta_ns
=
clockevent_delta2ns
(
0x30
,
cd
);
cd
->
rating
=
300
;
cd
->
irq
=
irq
;
cd
->
cpumask
=
cpumask_of_cpu
(
cpu
);
cd
->
set_next_event
=
mips_next_event
;
cd
->
set_mode
=
mips_set_mode
;
global_cd
[
cpu
]
=
cd
;
clockevents_register_device
(
cd
);
if
(
!
cp0_timer_irq_installed
)
{
#ifdef CONFIG_MIPS_MT_SMTC
#define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq)
setup_irq_smtc
(
irq
,
&
timer_irqaction
,
CPUCTR_IMASKBIT
);
#else
setup_irq
(
irq
,
&
timer_irqaction
);
#endif
/* CONFIG_MIPS_MT_SMTC */
cp0_timer_irq_installed
=
1
;
}
}
void
__init
time_init
(
void
)
void
__init
time_init
(
void
)
{
{
plat_time_init
();
plat_time_init
();
...
@@ -407,11 +387,6 @@ void __init time_init(void)
...
@@ -407,11 +387,6 @@ void __init time_init(void)
/* Calculate cache parameters. */
/* Calculate cache parameters. */
cycles_per_jiffy
=
cycles_per_jiffy
=
(
mips_hpt_frequency
+
HZ
/
2
)
/
HZ
;
(
mips_hpt_frequency
+
HZ
/
2
)
/
HZ
;
/*
* This sets up the high precision
* timer for the first interrupt.
*/
c0_hpt_timer_init
();
}
}
}
}
if
(
!
mips_hpt_frequency
)
if
(
!
mips_hpt_frequency
)
...
@@ -421,6 +396,10 @@ void __init time_init(void)
...
@@ -421,6 +396,10 @@ void __init time_init(void)
printk
(
"Using %u.%03u MHz high precision timer.
\n
"
,
printk
(
"Using %u.%03u MHz high precision timer.
\n
"
,
((
mips_hpt_frequency
+
500
)
/
1000
)
/
1000
,
((
mips_hpt_frequency
+
500
)
/
1000
)
/
1000
,
((
mips_hpt_frequency
+
500
)
/
1000
)
%
1000
);
((
mips_hpt_frequency
+
500
)
/
1000
)
%
1000
);
#ifdef CONFIG_IRQ_CPU
setup_irq
(
MIPS_CPU_IRQ_BASE
+
7
,
&
timer_irqaction
);
#endif
}
}
if
(
!
mips_timer_ack
)
if
(
!
mips_timer_ack
)
...
@@ -441,4 +420,5 @@ void __init time_init(void)
...
@@ -441,4 +420,5 @@ void __init time_init(void)
plat_timer_setup
(
&
timer_irqaction
);
plat_timer_setup
(
&
timer_irqaction
);
init_mips_clocksource
();
init_mips_clocksource
();
mips_clockevent_init
();
}
}
arch/mips/mips-boards/generic/time.c
View file @
7bcf7717
...
@@ -144,20 +144,20 @@ void __init plat_time_init(void)
...
@@ -144,20 +144,20 @@ void __init plat_time_init(void)
mips_scroll_message
();
mips_scroll_message
();
}
}
static
irqreturn_t
mips_perf_interrupt
(
int
irq
,
void
*
dev_id
)
//
static irqreturn_t mips_perf_interrupt(int irq, void *dev_id)
{
//
{
return
perf_irq
();
//
return perf_irq();
}
//
}
static
struct
irqaction
perf_irqaction
=
{
//
static struct irqaction perf_irqaction = {
.
handler
=
mips_perf_interrupt
,
//
.handler = mips_perf_interrupt,
.
flags
=
IRQF_DISABLED
|
IRQF_PERCPU
,
//
.flags = IRQF_DISABLED | IRQF_PERCPU,
.
name
=
"performance"
,
//
.name = "performance",
};
//
};
void
__init
plat_perf_setup
(
void
)
void
__init
plat_perf_setup
(
void
)
{
{
struct
irqaction
*
irq
=
&
perf_irqaction
;
//
struct irqaction *irq = &perf_irqaction;
cp0_perfcount_irq
=
-
1
;
cp0_perfcount_irq
=
-
1
;
...
@@ -170,12 +170,6 @@ void __init plat_perf_setup(void)
...
@@ -170,12 +170,6 @@ void __init plat_perf_setup(void)
if
(
cp0_perfcount_irq
>=
0
)
{
if
(
cp0_perfcount_irq
>=
0
)
{
if
(
cpu_has_vint
)
if
(
cpu_has_vint
)
set_vi_handler
(
cp0_perfcount_irq
,
mips_perf_dispatch
);
set_vi_handler
(
cp0_perfcount_irq
,
mips_perf_dispatch
);
#ifdef CONFIG_MIPS_MT_SMTC
setup_irq_smtc
(
cp0_perfcount_irq
,
irq
,
0x100
<<
cp0_perfcount_irq
);
#else
setup_irq
(
cp0_perfcount_irq
,
irq
);
#endif
/* CONFIG_MIPS_MT_SMTC */
#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
set_irq_handler
(
cp0_perfcount_irq
,
handle_percpu_irq
);
set_irq_handler
(
cp0_perfcount_irq
,
handle_percpu_irq
);
#endif
#endif
...
...
arch/mips/qemu/q-irq.c
View file @
7bcf7717
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
#include <linux/linkage.h>
#include <linux/linkage.h>
#include <asm/i8259.h>
#include <asm/i8259.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
#include <asm/mipsregs.h>
#include <asm/qemu.h>
#include <asm/qemu.h>
#include <asm/system.h>
#include <asm/system.h>
...
@@ -12,7 +13,7 @@ asmlinkage void plat_irq_dispatch(void)
...
@@ -12,7 +13,7 @@ asmlinkage void plat_irq_dispatch(void)
unsigned
int
pending
=
read_c0_status
()
&
read_c0_cause
();
unsigned
int
pending
=
read_c0_status
()
&
read_c0_cause
();
if
(
pending
&
0x8000
)
{
if
(
pending
&
0x8000
)
{
ll_timer_interrupt
(
Q_COUNT_COMPARE_IRQ
);
do_IRQ
(
Q_COUNT_COMPARE_IRQ
);
return
;
return
;
}
}
if
(
pending
&
0x0400
)
{
if
(
pending
&
0x0400
)
{
...
@@ -29,6 +30,7 @@ void __init arch_init_irq(void)
...
@@ -29,6 +30,7 @@ void __init arch_init_irq(void)
{
{
mips_hpt_frequency
=
QEMU_C0_COUNTER_CLOCK
;
/* 100MHz */
mips_hpt_frequency
=
QEMU_C0_COUNTER_CLOCK
;
/* 100MHz */
mips_cpu_irq_init
();
init_i8259_irqs
();
init_i8259_irqs
();
set_c0_status
(
0x8400
);
set_c0_status
(
0x8400
);
}
}
arch/mips/qemu/q-setup.c
View file @
7bcf7717
...
@@ -17,7 +17,6 @@ void __init plat_timer_setup(struct irqaction *irq)
...
@@ -17,7 +17,6 @@ void __init plat_timer_setup(struct irqaction *irq)
outb_p
(
0x34
,
0x43
);
/* binary, mode 2, LSB/MSB, ch 0 */
outb_p
(
0x34
,
0x43
);
/* binary, mode 2, LSB/MSB, ch 0 */
outb_p
(
LATCH
&
0xff
,
0x40
);
/* LSB */
outb_p
(
LATCH
&
0xff
,
0x40
);
/* LSB */
outb
(
LATCH
>>
8
,
0x40
);
/* MSB */
outb
(
LATCH
>>
8
,
0x40
);
/* MSB */
setup_irq
(
0
,
irq
);
}
}
void
__init
plat_mem_setup
(
void
)
void
__init
plat_mem_setup
(
void
)
...
...
arch/mips/sgi-ip22/ip22-int.c
View file @
7bcf7717
...
@@ -242,7 +242,7 @@ asmlinkage void plat_irq_dispatch(void)
...
@@ -242,7 +242,7 @@ asmlinkage void plat_irq_dispatch(void)
* First we check for r4k counter/timer IRQ.
* First we check for r4k counter/timer IRQ.
*/
*/
if
(
pending
&
CAUSEF_IP7
)
if
(
pending
&
CAUSEF_IP7
)
ll_timer_interrupt
(
SGI_TIMER_IRQ
,
NULL
);
do_IRQ
(
SGI_TIMER_IRQ
);
else
if
(
pending
&
CAUSEF_IP2
)
else
if
(
pending
&
CAUSEF_IP2
)
indy_local0_irqdispatch
();
indy_local0_irqdispatch
();
else
if
(
pending
&
CAUSEF_IP3
)
else
if
(
pending
&
CAUSEF_IP3
)
...
...
arch/mips/sgi-ip32/ip32-irq.c
View file @
7bcf7717
...
@@ -457,7 +457,7 @@ static void ip32_irq4(void)
...
@@ -457,7 +457,7 @@ static void ip32_irq4(void)
static
void
ip32_irq5
(
void
)
static
void
ip32_irq5
(
void
)
{
{
ll_timer_interrupt
(
IP32_R4K_TIMER_IRQ
);
do_IRQ
(
IP32_R4K_TIMER_IRQ
);
}
}
asmlinkage
void
plat_irq_dispatch
(
void
)
asmlinkage
void
plat_irq_dispatch
(
void
)
...
...
arch/mips/sibyte/Kconfig
View file @
7bcf7717
config SIBYTE_SB1250
config SIBYTE_SB1250
bool
bool
select HW_HAS_PCI
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_ENABLE_LDT_IF_PCI
select SIBYTE_ENABLE_LDT_IF_PCI
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
select SIBYTE_SB1xxx_SOC
...
@@ -8,6 +9,7 @@ config SIBYTE_SB1250
...
@@ -8,6 +9,7 @@ config SIBYTE_SB1250
config SIBYTE_BCM1120
config SIBYTE_BCM1120
bool
bool
select IRQ_CPU
select SIBYTE_BCM112X
select SIBYTE_BCM112X
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
select SIBYTE_SB1xxx_SOC
...
@@ -15,6 +17,7 @@ config SIBYTE_BCM1120
...
@@ -15,6 +17,7 @@ config SIBYTE_BCM1120
config SIBYTE_BCM1125
config SIBYTE_BCM1125
bool
bool
select HW_HAS_PCI
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_BCM112X
select SIBYTE_BCM112X
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
select SIBYTE_SB1xxx_SOC
...
@@ -22,6 +25,7 @@ config SIBYTE_BCM1125
...
@@ -22,6 +25,7 @@ config SIBYTE_BCM1125
config SIBYTE_BCM1125H
config SIBYTE_BCM1125H
bool
bool
select HW_HAS_PCI
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_BCM112X
select SIBYTE_BCM112X
select SIBYTE_ENABLE_LDT_IF_PCI
select SIBYTE_ENABLE_LDT_IF_PCI
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_HAS_ZBUS_PROFILING
...
@@ -29,12 +33,14 @@ config SIBYTE_BCM1125H
...
@@ -29,12 +33,14 @@ config SIBYTE_BCM1125H
config SIBYTE_BCM112X
config SIBYTE_BCM112X
bool
bool
select IRQ_CPU
select SIBYTE_SB1xxx_SOC
select SIBYTE_SB1xxx_SOC
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_HAS_ZBUS_PROFILING
config SIBYTE_BCM1x80
config SIBYTE_BCM1x80
bool
bool
select HW_HAS_PCI
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
select SIBYTE_SB1xxx_SOC
select SYS_SUPPORTS_SMP
select SYS_SUPPORTS_SMP
...
@@ -42,6 +48,7 @@ config SIBYTE_BCM1x80
...
@@ -42,6 +48,7 @@ config SIBYTE_BCM1x80
config SIBYTE_BCM1x55
config SIBYTE_BCM1x55
bool
bool
select HW_HAS_PCI
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_SB1xxx_SOC
select SIBYTE_SB1xxx_SOC
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_HAS_ZBUS_PROFILING
select SYS_SUPPORTS_SMP
select SYS_SUPPORTS_SMP
...
@@ -49,6 +56,7 @@ config SIBYTE_BCM1x55
...
@@ -49,6 +56,7 @@ config SIBYTE_BCM1x55
config SIBYTE_SB1xxx_SOC
config SIBYTE_SB1xxx_SOC
bool
bool
select DMA_COHERENT
select DMA_COHERENT
select IRQ_CPU
select SIBYTE_CFE
select SIBYTE_CFE
select SWAP_IO_SPACE
select SWAP_IO_SPACE
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_32BIT_KERNEL
...
@@ -166,10 +174,6 @@ config SIBYTE_BW_TRACE
...
@@ -166,10 +174,6 @@ config SIBYTE_BW_TRACE
buffer activity. Raw buffer data is dumped to console, and
buffer activity. Raw buffer data is dumped to console, and
must be processed off-line.
must be processed off-line.
config SIBYTE_SB1250_PROF
bool "Support for SB1/SOC profiling - SB1/SCD perf counters"
depends on SIBYTE_SB1xxx_SOC
config SIBYTE_TBPROF
config SIBYTE_TBPROF
tristate "Support for ZBbus profiling"
tristate "Support for ZBbus profiling"
depends on SIBYTE_HAS_ZBUS_PROFILING
depends on SIBYTE_HAS_ZBUS_PROFILING
...
...
arch/mips/sibyte/bcm1480/irq.c
View file @
7bcf7717
...
@@ -450,7 +450,6 @@ static void bcm1480_kgdb_interrupt(void)
...
@@ -450,7 +450,6 @@ static void bcm1480_kgdb_interrupt(void)
#endif
/* CONFIG_KGDB */
#endif
/* CONFIG_KGDB */
extern
void
bcm1480_timer_interrupt
(
void
);
extern
void
bcm1480_mailbox_interrupt
(
void
);
extern
void
bcm1480_mailbox_interrupt
(
void
);
asmlinkage
void
plat_irq_dispatch
(
void
)
asmlinkage
void
plat_irq_dispatch
(
void
)
...
@@ -470,8 +469,16 @@ asmlinkage void plat_irq_dispatch(void)
...
@@ -470,8 +469,16 @@ asmlinkage void plat_irq_dispatch(void)
else
else
#endif
#endif
if
(
pending
&
CAUSEF_IP4
)
if
(
pending
&
CAUSEF_IP4
)
{
bcm1480_timer_interrupt
();
int
cpu
=
smp_processor_id
();
int
irq
=
K_BCM1480_INT_TIMER_0
+
cpu
;
/* Reset the timer */
__raw_writeq
(
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
)));
do_IRQ
(
irq
);
}
#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
else
if
(
pending
&
CAUSEF_IP3
)
else
if
(
pending
&
CAUSEF_IP3
)
...
...
arch/mips/sibyte/sb1250/irq.c
View file @
7bcf7717
...
@@ -28,6 +28,7 @@
...
@@ -28,6 +28,7 @@
#include <asm/errno.h>
#include <asm/errno.h>
#include <asm/signal.h>
#include <asm/signal.h>
#include <asm/system.h>
#include <asm/system.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/io.h>
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/sb1250_regs.h>
...
@@ -399,18 +400,45 @@ static void sb1250_kgdb_interrupt(void)
...
@@ -399,18 +400,45 @@ static void sb1250_kgdb_interrupt(void)
#endif
/* CONFIG_KGDB */
#endif
/* CONFIG_KGDB */
extern
void
sb1250_timer_interrupt
(
void
);
static
inline
void
sb1250_timer_interrupt
(
void
)
{
int
cpu
=
smp_processor_id
();
int
irq
=
K_INT_TIMER_0
+
cpu
;
irq_enter
();
kstat_this_cpu
.
irqs
[
irq
]
++
;
write_seqlock
(
&
xtime_lock
);
/* ACK interrupt */
____raw_writeq
(
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
)));
/*
* call the generic timer interrupt handling
*/
do_timer
(
1
);
write_sequnlock
(
&
xtime_lock
);
/*
* In UP mode, we call local_timer_interrupt() to do profiling
* and process accouting.
*
* In SMP mode, local_timer_interrupt() is invoked by appropriate
* low-level local timer interrupt handler.
*/
local_timer_interrupt
(
irq
);
irq_exit
();
}
extern
void
sb1250_mailbox_interrupt
(
void
);
extern
void
sb1250_mailbox_interrupt
(
void
);
asmlinkage
void
plat_irq_dispatch
(
void
)
asmlinkage
void
plat_irq_dispatch
(
void
)
{
{
unsigned
int
pending
;
unsigned
int
pending
;
#ifdef CONFIG_SIBYTE_SB1250_PROF
/* Set compare to count to silence count/compare timer interrupts */
write_c0_compare
(
read_c0_count
());
#endif
/*
/*
* What a pain. We have to be really careful saving the upper 32 bits
* What a pain. We have to be really careful saving the upper 32 bits
* of any * register across function calls if we don't want them
* of any * register across function calls if we don't want them
...
@@ -423,13 +451,9 @@ asmlinkage void plat_irq_dispatch(void)
...
@@ -423,13 +451,9 @@ asmlinkage void plat_irq_dispatch(void)
pending
=
read_c0_cause
()
&
read_c0_status
()
&
ST0_IM
;
pending
=
read_c0_cause
()
&
read_c0_status
()
&
ST0_IM
;
#ifdef CONFIG_SIBYTE_SB1250_PROF
if
(
pending
&
CAUSEF_IP7
)
/* CPU performance counter interrupt */
if
(
pending
&
CAUSEF_IP7
)
/* Cpu performance counter interrupt */
do_IRQ
(
MIPS_CPU_IRQ_BASE
+
7
);
sbprof_cpu_intr
();
else
if
(
pending
&
CAUSEF_IP4
)
else
#endif
if
(
pending
&
CAUSEF_IP4
)
sb1250_timer_interrupt
();
sb1250_timer_interrupt
();
#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
...
...
arch/mips/sibyte/sb1250/time.c
View file @
7bcf7717
...
@@ -116,18 +116,6 @@ void sb1250_time_init(void)
...
@@ -116,18 +116,6 @@ void sb1250_time_init(void)
*/
*/
}
}
void
sb1250_timer_interrupt
(
void
)
{
int
cpu
=
smp_processor_id
();
int
irq
=
K_INT_TIMER_0
+
cpu
;
/* ACK interrupt */
____raw_writeq
(
M_SCD_TIMER_ENABLE
|
M_SCD_TIMER_MODE_CONTINUOUS
,
IOADDR
(
A_SCD_TIMER_REGISTER
(
cpu
,
R_SCD_TIMER_CFG
)));
ll_timer_interrupt
(
irq
);
}
/*
/*
* The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
* The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
* again.
* again.
...
...
include/asm-mips/mach-ip27/irq.h
View file @
7bcf7717
...
@@ -17,4 +17,6 @@
...
@@ -17,4 +17,6 @@
*/
*/
#define NR_IRQS 256
#define NR_IRQS 256
#include_next <irq.h>
#endif
/* __ASM_MACH_IP27_IRQ_H */
#endif
/* __ASM_MACH_IP27_IRQ_H */
include/asm-mips/qemu.h
View file @
7bcf7717
...
@@ -12,7 +12,7 @@
...
@@ -12,7 +12,7 @@
* Interrupt numbers
* Interrupt numbers
*/
*/
#define Q_PIC_IRQ_BASE 0
#define Q_PIC_IRQ_BASE 0
#define Q_COUNT_COMPARE_IRQ
16
#define Q_COUNT_COMPARE_IRQ
23
/*
/*
* Qemu clock rate. Unlike on real MIPS this has no relation to the
* Qemu clock rate. Unlike on real MIPS this has no relation to the
...
...
include/asm-mips/time.h
View file @
7bcf7717
...
@@ -48,11 +48,6 @@ extern void (*mips_timer_ack)(void);
...
@@ -48,11 +48,6 @@ extern void (*mips_timer_ack)(void);
*/
*/
extern
struct
clocksource
clocksource_mips
;
extern
struct
clocksource
clocksource_mips
;
/*
* The low-level timer interrupt routine.
*/
extern
void
ll_timer_interrupt
(
int
irq
,
void
*
dev_id
);
/*
/*
* profiling and process accouting is done separately in local_timer_interrupt
* profiling and process accouting is done separately in local_timer_interrupt
*/
*/
...
@@ -78,4 +73,9 @@ extern unsigned int mips_hpt_frequency;
...
@@ -78,4 +73,9 @@ extern unsigned int mips_hpt_frequency;
*/
*/
extern
int
(
*
perf_irq
)(
void
);
extern
int
(
*
perf_irq
)(
void
);
/*
* Initialize the calling CPU's compare interrupt as clockevent device
*/
extern
void
mips_clockevent_init
(
void
);
#endif
/* _ASM_TIME_H */
#endif
/* _ASM_TIME_H */
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