Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 010c108d authored by David VomLehn's avatar David VomLehn Committed by Ralf Baechle
Browse files

MIPS: PowerTV: Fix support for timer interrupts with > 64 external IRQs



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: default avatarDavid VomLehn <(dvomlehn@cisco.com)>
To: linux-mips@linux-mips.org
Patchwork: http://patchwork.linux-mips.org/patch/804/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 59dfa2fc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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.
 *
@@ -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)

+1 −1
Original line number Diff line number Diff line
@@ -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);
}

/*
+4 −2
Original line number Diff line number Diff line
@@ -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
@@ -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 {