Skip to content

Commit

Permalink
MIPS: PowerTV: Fix support for timer interrupts with > 64 external IRQs
Browse files Browse the repository at this point in the history
The MIPS processor is limited to 64 external interrupt sources. Using a
greater number without IRQ sharing requires reading platform-specific
registers. On such platforms, reading the IntCtl register to determine
which interrupt corresponds to a timer interrupt will not work.

On MIPSR2 systems there is a solution - the TI bit in the Cause register,
specifically indicates that a timer interrupt has occured. This patch uses
that bit to detect interrupts for MIPSR2 processors, which may be expected
to work regardless of how the timer interrupt may be routed in the hardware.

Signed-off-by: David VomLehn ([email protected])
To: [email protected]
Patchwork: http://patchwork.linux-mips.org/patch/804/
Signed-off-by: Ralf Baechle <[email protected]>
  • Loading branch information
David VomLehn authored and ralfbaechle committed Jan 27, 2010
1 parent 59dfa2f commit 010c108
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 3 deletions.
1 change: 1 addition & 0 deletions arch/mips/include/asm/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ extern void free_irqno(unsigned int irq);
#define CP0_LEGACY_COMPARE_IRQ 7

extern int cp0_compare_irq;
extern int cp0_compare_irq_shift;
extern int cp0_perfcount_irq;

#endif /* _ASM_IRQ_H */
12 changes: 12 additions & 0 deletions arch/mips/include/asm/mipsregs.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,16 @@
#define ST0_CU3 0x80000000
#define ST0_XX 0x80000000 /* MIPS IV naming */

/*
* Bitfields and bit numbers in the coprocessor 0 IntCtl register. (MIPSR2)
*
* Refer to your MIPS R4xx0 manual, chapter 5 for explanation.
*/
#define INTCTLB_IPPCI 26
#define INTCTLF_IPPCI (_ULCAST_(7) << INTCTLB_IPPCI)
#define INTCTLB_IPTI 29
#define INTCTLF_IPTI (_ULCAST_(7) << INTCTLB_IPTI)

/*
* Bitfields and bit numbers in the coprocessor 0 cause register.
*
Expand Down Expand Up @@ -434,6 +444,8 @@
#define CAUSEF_IV (_ULCAST_(1) << 23)
#define CAUSEB_CE 28
#define CAUSEF_CE (_ULCAST_(3) << 28)
#define CAUSEB_TI 30
#define CAUSEF_TI (_ULCAST_(1) << 30)
#define CAUSEB_BD 31
#define CAUSEF_BD (_ULCAST_(1) << 31)

Expand Down
2 changes: 1 addition & 1 deletion arch/mips/kernel/cevt-r4k.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ void mips_event_handler(struct clock_event_device *dev)
*/
static int c0_compare_int_pending(void)
{
return (read_c0_cause() >> cp0_compare_irq) & 0x100;
return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP);
}

/*
Expand Down
6 changes: 4 additions & 2 deletions arch/mips/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -1403,6 +1403,7 @@ extern void flush_tlb_handlers(void);
* Timer interrupt
*/
int cp0_compare_irq;
int cp0_compare_irq_shift;

/*
* Performance counter IRQ or -1 if shared with timer
Expand Down Expand Up @@ -1493,8 +1494,9 @@ void __cpuinit per_cpu_trap_init(void)
* o read IntCtl.IPPCI to determine the performance counter interrupt
*/
if (cpu_has_mips_r2) {
cp0_compare_irq = (read_c0_intctl() >> 29) & 7;
cp0_perfcount_irq = (read_c0_intctl() >> 26) & 7;
cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP;
cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7;
cp0_perfcount_irq = (read_c0_intctl() >> INTCTLB_IPPCI) & 7;
if (cp0_perfcount_irq == cp0_compare_irq)
cp0_perfcount_irq = -1;
} else {
Expand Down

0 comments on commit 010c108

Please sign in to comment.