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
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
select GENERIC_ISA_DMA
select HAVE_STD_PC_SERIAL_PORT
select I8259
select IRQ_CPU
select ISA
select PCSPEAKER
select SWAP_IO_SPACE
...
...
@@ -667,6 +668,10 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
config GENERIC_CLOCKEVENTS
bool
default y
config GENERIC_TIME
bool
default y
...
...
@@ -901,6 +906,8 @@ config BOOT_ELF64
menu "CPU selection"
source "kernel/time/Kconfig"
choice
prompt "CPU type"
default CPU_R4X00
...
...
arch/mips/au1000/common/irq.c
View file @
7bcf7717
...
...
@@ -633,7 +633,7 @@ asmlinkage void plat_irq_dispatch(void)
unsigned
int
pending
=
read_c0_status
()
&
read_c0_cause
()
&
ST0_IM
;
if
(
pending
&
CAUSEF_IP7
)
ll_timer_interrupt
(
63
);
do_IRQ
(
63
);
else
if
(
pending
&
CAUSEF_IP2
)
intc0_req0_irqdispatch
();
else
if
(
pending
&
CAUSEF_IP3
)
...
...
arch/mips/configs/bigsur_defconfig
View file @
7bcf7717
...
...
@@ -69,7 +69,6 @@ CONFIG_SIBYTE_SB1xxx_SOC=y
CONFIG_SIBYTE_CFE=y
# CONFIG_SIBYTE_CFE_CONSOLE is not set
# CONFIG_SIBYTE_BUS_WATCHER is not set
# CONFIG_SIBYTE_SB1250_PROF is not set
# CONFIG_SIBYTE_TBPROF is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# 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
CONFIG_SIBYTE_CFE=y
# CONFIG_SIBYTE_CFE_CONSOLE is not set
# CONFIG_SIBYTE_BUS_WATCHER is not set
# CONFIG_SIBYTE_SB1250_PROF is not set
# CONFIG_SIBYTE_TBPROF is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
...
...
arch/mips/kernel/process.c
View file @
7bcf7717
...
...
@@ -11,6 +11,7 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/tick.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
...
...
@@ -52,6 +53,7 @@ void __noreturn cpu_idle(void)
{
/* endless idle loop with no priority at all */
while
(
1
)
{
tick_nohz_stop_sched_tick
();
while
(
!
need_resched
())
{
#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
extern
void
smtc_idle_loop_hook
(
void
);
...
...
@@ -61,6 +63,7 @@ void __noreturn cpu_idle(void)
if
(
cpu_wait
)
(
*
cpu_wait
)();
}
tick_nohz_restart_sched_tick
();
preempt_enable_no_resched
();
schedule
();
preempt_disable
();
...
...
arch/mips/kernel/smp.c
View file @
7bcf7717
...
...
@@ -38,6 +38,7 @@
#include <asm/system.h>
#include <asm/mmu_context.h>
#include <asm/smp.h>
#include <asm/time.h>
#ifdef CONFIG_MIPS_MT_SMTC
#include <asm/mipsmtregs.h>
...
...
@@ -70,6 +71,7 @@ asmlinkage __cpuinit void start_secondary(void)
cpu_probe
();
cpu_report
();
per_cpu_trap_init
();
mips_clockevent_init
();
prom_init_secondary
();
/*
...
...
arch/mips/kernel/smtc.c
View file @
7bcf7717
...
...
@@ -867,7 +867,7 @@ void ipi_decode(struct smtc_ipi *pipi)
#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
clock_hang_reported
[
dest_copy
]
=
0
;
#endif
/* CONFIG_SMTC_IDLE_HOOK_DEBUG */
local_timer_interrupt
(
0
);
local_timer_interrupt
(
0
,
NULL
);
irq_exit
();
break
;
case
LINUX_SMP_IPI
:
...
...
arch/mips/kernel/time.c
View file @
7bcf7717
...
...
@@ -11,6 +11,7 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/clockchips.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
...
...
@@ -34,6 +35,8 @@
#include <asm/sections.h>
#include <asm/time.h>
#include <irq.h>
/*
* 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
...
...
@@ -70,10 +73,6 @@ int update_persistent_clock(struct timespec now)
/* how many counter cycles in a jiffy */
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).
*/
...
...
@@ -92,18 +91,7 @@ static cycle_t null_hpt_read(void)
*/
static
void
c0_timer_ack
(
void
)
{
unsigned
int
count
;
/* 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
);
}
write_c0_compare
(
read_c0_compare
());
}
/*
...
...
@@ -114,13 +102,6 @@ static cycle_t c0_hpt_read(void)
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
);
void
(
*
mips_timer_ack
)(
void
);
...
...
@@ -140,35 +121,6 @@ void local_timer_interrupt(int irq, void *dev_id)
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
)
{
return
0
;
...
...
@@ -209,81 +161,6 @@ static inline int handle_perf_irq (int 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.
*
...
...
@@ -301,12 +178,6 @@ void ll_timer_interrupt(int irq, void *dev_id)
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
)
{
cycle_t
frequency
,
hpt_start
,
hpt_end
,
hpt_count
,
hz
;
...
...
@@ -355,6 +226,65 @@ struct clocksource clocksource_mips = {
.
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
)
{
u64
temp
;
...
...
@@ -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
)
{
plat_time_init
();
...
...
@@ -407,11 +387,6 @@ void __init time_init(void)
/* Calculate cache parameters. */
cycles_per_jiffy
=
(
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
)
...
...
@@ -421,6 +396,10 @@ void __init time_init(void)
printk
(
"Using %u.%03u MHz high precision timer.
\n
"
,
((
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
)
...
...
@@ -441,4 +420,5 @@ void __init time_init(void)
plat_timer_setup
(
&
timer_irqaction
);
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)
mips_scroll_message
();
}
static
irqreturn_t
mips_perf_interrupt
(
int
irq
,
void
*
dev_id
)
{
return
perf_irq
();
}
//
static irqreturn_t mips_perf_interrupt(int irq, void *dev_id)
//
{
//
return perf_irq();
//
}
static
struct
irqaction
perf_irqaction
=
{
.
handler
=
mips_perf_interrupt
,
.
flags
=
IRQF_DISABLED
|
IRQF_PERCPU
,
.
name
=
"performance"
,
};
//
static struct irqaction perf_irqaction = {
//
.handler = mips_perf_interrupt,
//
.flags = IRQF_DISABLED | IRQF_PERCPU,
//
.name = "performance",
//
};
void
__init
plat_perf_setup
(
void
)
{
struct
irqaction
*
irq
=
&
perf_irqaction
;
//
struct irqaction *irq = &perf_irqaction;
cp0_perfcount_irq
=
-
1
;
...
...
@@ -170,12 +170,6 @@ void __init plat_perf_setup(void)
if
(
cp0_perfcount_irq
>=
0
)
{
if
(
cpu_has_vint
)
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
set_irq_handler
(
cp0_perfcount_irq
,
handle_percpu_irq
);
#endif
...
...
arch/mips/qemu/q-irq.c
View file @
7bcf7717
...
...
@@ -2,6 +2,7 @@
#include <linux/linkage.h>
#include <asm/i8259.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
#include <asm/qemu.h>
#include <asm/system.h>
...
...
@@ -12,7 +13,7 @@ asmlinkage void plat_irq_dispatch(void)
unsigned
int
pending
=
read_c0_status
()
&
read_c0_cause
();
if
(
pending
&
0x8000
)
{
ll_timer_interrupt
(
Q_COUNT_COMPARE_IRQ
);
do_IRQ
(
Q_COUNT_COMPARE_IRQ
);
return
;
}
if
(
pending
&
0x0400
)
{
...
...
@@ -29,6 +30,7 @@ void __init arch_init_irq(void)
{
mips_hpt_frequency
=
QEMU_C0_COUNTER_CLOCK
;
/* 100MHz */
mips_cpu_irq_init
();
init_i8259_irqs
();
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)
outb_p
(
0x34
,
0x43
);
/* binary, mode 2, LSB/MSB, ch 0 */
outb_p
(
LATCH
&
0xff
,
0x40
);
/* LSB */
outb
(
LATCH
>>
8
,
0x40
);
/* MSB */
setup_irq
(
0
,
irq
);
}
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)
* First we check for r4k counter/timer IRQ.
*/
if
(
pending
&
CAUSEF_IP7
)
ll_timer_interrupt
(
SGI_TIMER_IRQ
,
NULL
);
do_IRQ
(
SGI_TIMER_IRQ
);
else
if
(
pending
&
CAUSEF_IP2
)
indy_local0_irqdispatch
();
else
if
(
pending
&
CAUSEF_IP3
)
...
...
arch/mips/sgi-ip32/ip32-irq.c
View file @
7bcf7717
...
...
@@ -457,7 +457,7 @@ static void ip32_irq4(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
)
...
...
arch/mips/sibyte/Kconfig
View file @
7bcf7717
config SIBYTE_SB1250
bool
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_ENABLE_LDT_IF_PCI
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
...
...
@@ -8,6 +9,7 @@ config SIBYTE_SB1250
config SIBYTE_BCM1120
bool
select IRQ_CPU
select SIBYTE_BCM112X
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
...
...
@@ -15,6 +17,7 @@ config SIBYTE_BCM1120
config SIBYTE_BCM1125
bool
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_BCM112X
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
...
...
@@ -22,6 +25,7 @@ config SIBYTE_BCM1125
config SIBYTE_BCM1125H
bool
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_BCM112X
select SIBYTE_ENABLE_LDT_IF_PCI
select SIBYTE_HAS_ZBUS_PROFILING
...
...
@@ -29,12 +33,14 @@ config SIBYTE_BCM1125H
config SIBYTE_BCM112X
bool
select IRQ_CPU
select SIBYTE_SB1xxx_SOC
select SIBYTE_HAS_ZBUS_PROFILING
config SIBYTE_BCM1x80
bool
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
select SYS_SUPPORTS_SMP
...
...
@@ -42,6 +48,7 @@ config SIBYTE_BCM1x80
config SIBYTE_BCM1x55
bool
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_SB1xxx_SOC
select SIBYTE_HAS_ZBUS_PROFILING
select SYS_SUPPORTS_SMP
...
...
@@ -49,6 +56,7 @@ config SIBYTE_BCM1x55
config SIBYTE_SB1xxx_SOC
bool
select DMA_COHERENT
select IRQ_CPU
select SIBYTE_CFE
select SWAP_IO_SPACE
select SYS_SUPPORTS_32BIT_KERNEL
...
...
@@ -166,10 +174,6 @@ config SIBYTE_BW_TRACE
buffer activity. Raw buffer data is dumped to console, and
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
tristate "Support for ZBbus 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)
#endif
/* CONFIG_KGDB */
extern
void
bcm1480_timer_interrupt
(
void
);
extern
void
bcm1480_mailbox_interrupt
(
void
);
asmlinkage
void
plat_irq_dispatch
(
void
)
...
...
@@ -470,8 +469,16 @@ asmlinkage void plat_irq_dispatch(void)
else
#endif
if
(
pending
&
CAUSEF_IP4
)
bcm1480_timer_interrupt
();
if
(
pending
&
CAUSEF_IP4
)
{
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
else
if
(
pending
&
CAUSEF_IP3
)
...
...
arch/mips/sibyte/sb1250/irq.c
View file @
7bcf7717
...
...
@@ -28,6 +28,7 @@
#include <asm/errno.h>
#include <asm/signal.h>
#include <asm/system.h>
#include <asm/time.h>
#include <asm/io.h>
#include <asm/sibyte/sb1250_regs.h>
...
...
@@ -399,18 +400,45 @@ static void sb1250_kgdb_interrupt(void)
#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
);
asmlinkage
void
plat_irq_dispatch
(
void
)
{
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
* of any * register across function calls if we don't want them
...
...
@@ -423,13 +451,9 @@ asmlinkage void plat_irq_dispatch(void)
pending
=
read_c0_cause
()
&
read_c0_status
()
&
ST0_IM
;
#ifdef CONFIG_SIBYTE_SB1250_PROF
if
(
pending
&
CAUSEF_IP7
)
/* Cpu performance counter interrupt */
sbprof_cpu_intr
();
else
#endif
if
(
pending
&
CAUSEF_IP4
)
if
(
pending
&
CAUSEF_IP7
)
/* CPU performance counter interrupt */
do_IRQ
(
MIPS_CPU_IRQ_BASE
+
7
);
else
if
(
pending
&
CAUSEF_IP4
)
sb1250_timer_interrupt
();
#ifdef CONFIG_SMP
...
...
arch/mips/sibyte/sb1250/time.c
View file @
7bcf7717
...
...
@@ -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
* again.
...
...
include/asm-mips/mach-ip27/irq.h
View file @
7bcf7717
...
...
@@ -17,4 +17,6 @@
*/
#define NR_IRQS 256
#include_next <irq.h>
#endif
/* __ASM_MACH_IP27_IRQ_H */
include/asm-mips/qemu.h
View file @
7bcf7717
...
...
@@ -12,7 +12,7 @@
* Interrupt numbers
*/
#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
...
...
include/asm-mips/time.h
View file @
7bcf7717
...
...
@@ -48,11 +48,6 @@ extern void (*mips_timer_ack)(void);
*/
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
*/
...
...
@@ -78,4 +73,9 @@ extern unsigned int mips_hpt_frequency;
*/
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 */
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