CRIS v32: Update and simplify kernel/irq.c.

- First timer register has changed name to timer0.
- Build IRQs with only IRQ number, mask bit will be calculated instead.
- Add more IRQs, up to 64 supported.
- Use arrays to hold which IRQs triggered instead of trying to do magic
  with two 32 bit values now that more than 32 IRQs are supported.
This commit is contained in:
Jesper Nilsson 2007-11-30 18:09:54 +01:00
Родитель 96e476697d
Коммит 693d9847b2
1 изменённых файлов: 190 добавлений и 78 удалений

Просмотреть файл

@ -15,15 +15,21 @@
#include <linux/threads.h>
#include <linux/spinlock.h>
#include <linux/kernel_stat.h>
#include <asm/arch/hwregs/reg_map.h>
#include <asm/arch/hwregs/reg_rdwr.h>
#include <asm/arch/hwregs/intr_vect.h>
#include <asm/arch/hwregs/intr_vect_defs.h>
#include <hwregs/reg_map.h>
#include <hwregs/reg_rdwr.h>
#include <hwregs/intr_vect.h>
#include <hwregs/intr_vect_defs.h>
#define CPU_FIXED -1
/* IRQ masks (refer to comment for crisv32_do_multiple) */
#define TIMER_MASK (1 << (TIMER_INTR_VECT - FIRST_IRQ))
#if TIMER0_INTR_VECT - FIRST_IRQ < 32
#define TIMER_MASK (1 << (TIMER0_INTR_VECT - FIRST_IRQ))
#undef TIMER_VECT1
#else
#define TIMER_MASK (1 << (TIMER0_INTR_VECT - FIRST_IRQ - 32))
#define TIMER_VECT1
#endif
#ifdef CONFIG_ETRAX_KGDB
#if defined(CONFIG_ETRAX_KGDB_PORT0)
#define IGNOREMASK (1 << (SER0_INTR_VECT - FIRST_IRQ))
@ -44,8 +50,8 @@ struct cris_irq_allocation
cpumask_t mask; /* The CPUs to which the IRQ may be allocated. */
};
struct cris_irq_allocation irq_allocations[NR_IRQS] =
{[0 ... NR_IRQS - 1] = {0, CPU_MASK_ALL}};
struct cris_irq_allocation irq_allocations[NR_REAL_IRQS] =
{ [0 ... NR_REAL_IRQS - 1] = {0, CPU_MASK_ALL} };
static unsigned long irq_regs[NR_CPUS] =
{
@ -55,6 +61,12 @@ static unsigned long irq_regs[NR_CPUS] =
#endif
};
#if NR_REAL_IRQS > 32
#define NBR_REGS 2
#else
#define NBR_REGS 1
#endif
unsigned long cpu_irq_counters[NR_CPUS];
unsigned long irq_counters[NR_REAL_IRQS];
@ -79,45 +91,81 @@ extern void d_mmu_write(void);
extern void kgdb_init(void);
extern void breakpoint(void);
/* From traps.c. */
extern void breakh_BUG(void);
/*
* Build the IRQ handler stubs using macros from irq.h. First argument is the
* IRQ number, the second argument is the corresponding bit in
* intr_rw_vect_mask found in asm/arch/hwregs/intr_vect_defs.h.
* Build the IRQ handler stubs using macros from irq.h.
*/
BUILD_IRQ(0x31, (1 << 0)) /* memarb */
BUILD_IRQ(0x32, (1 << 1)) /* gen_io */
BUILD_IRQ(0x33, (1 << 2)) /* iop0 */
BUILD_IRQ(0x34, (1 << 3)) /* iop1 */
BUILD_IRQ(0x35, (1 << 4)) /* iop2 */
BUILD_IRQ(0x36, (1 << 5)) /* iop3 */
BUILD_IRQ(0x37, (1 << 6)) /* dma0 */
BUILD_IRQ(0x38, (1 << 7)) /* dma1 */
BUILD_IRQ(0x39, (1 << 8)) /* dma2 */
BUILD_IRQ(0x3a, (1 << 9)) /* dma3 */
BUILD_IRQ(0x3b, (1 << 10)) /* dma4 */
BUILD_IRQ(0x3c, (1 << 11)) /* dma5 */
BUILD_IRQ(0x3d, (1 << 12)) /* dma6 */
BUILD_IRQ(0x3e, (1 << 13)) /* dma7 */
BUILD_IRQ(0x3f, (1 << 14)) /* dma8 */
BUILD_IRQ(0x40, (1 << 15)) /* dma9 */
BUILD_IRQ(0x41, (1 << 16)) /* ata */
BUILD_IRQ(0x42, (1 << 17)) /* sser0 */
BUILD_IRQ(0x43, (1 << 18)) /* sser1 */
BUILD_IRQ(0x44, (1 << 19)) /* ser0 */
BUILD_IRQ(0x45, (1 << 20)) /* ser1 */
BUILD_IRQ(0x46, (1 << 21)) /* ser2 */
BUILD_IRQ(0x47, (1 << 22)) /* ser3 */
BUILD_IRQ(0x48, (1 << 23))
BUILD_IRQ(0x49, (1 << 24)) /* eth0 */
BUILD_IRQ(0x4a, (1 << 25)) /* eth1 */
BUILD_TIMER_IRQ(0x4b, (1 << 26))/* timer */
BUILD_IRQ(0x4c, (1 << 27)) /* bif_arb */
BUILD_IRQ(0x4d, (1 << 28)) /* bif_dma */
BUILD_IRQ(0x4e, (1 << 29)) /* ext */
BUILD_IRQ(0x4f, (1 << 29)) /* ipi */
BUILD_IRQ(0x31)
BUILD_IRQ(0x32)
BUILD_IRQ(0x33)
BUILD_IRQ(0x34)
BUILD_IRQ(0x35)
BUILD_IRQ(0x36)
BUILD_IRQ(0x37)
BUILD_IRQ(0x38)
BUILD_IRQ(0x39)
BUILD_IRQ(0x3a)
BUILD_IRQ(0x3b)
BUILD_IRQ(0x3c)
BUILD_IRQ(0x3d)
BUILD_IRQ(0x3e)
BUILD_IRQ(0x3f)
BUILD_IRQ(0x40)
BUILD_IRQ(0x41)
BUILD_IRQ(0x42)
BUILD_IRQ(0x43)
BUILD_IRQ(0x44)
BUILD_IRQ(0x45)
BUILD_IRQ(0x46)
BUILD_IRQ(0x47)
BUILD_IRQ(0x48)
BUILD_IRQ(0x49)
BUILD_IRQ(0x4a)
BUILD_IRQ(0x4b)
BUILD_IRQ(0x4c)
BUILD_IRQ(0x4d)
BUILD_IRQ(0x4e)
BUILD_IRQ(0x4f)
BUILD_IRQ(0x50)
#if MACH_IRQS > 32
BUILD_IRQ(0x51)
BUILD_IRQ(0x52)
BUILD_IRQ(0x53)
BUILD_IRQ(0x54)
BUILD_IRQ(0x55)
BUILD_IRQ(0x56)
BUILD_IRQ(0x57)
BUILD_IRQ(0x58)
BUILD_IRQ(0x59)
BUILD_IRQ(0x5a)
BUILD_IRQ(0x5b)
BUILD_IRQ(0x5c)
BUILD_IRQ(0x5d)
BUILD_IRQ(0x5e)
BUILD_IRQ(0x5f)
BUILD_IRQ(0x60)
BUILD_IRQ(0x61)
BUILD_IRQ(0x62)
BUILD_IRQ(0x63)
BUILD_IRQ(0x64)
BUILD_IRQ(0x65)
BUILD_IRQ(0x66)
BUILD_IRQ(0x67)
BUILD_IRQ(0x68)
BUILD_IRQ(0x69)
BUILD_IRQ(0x6a)
BUILD_IRQ(0x6b)
BUILD_IRQ(0x6c)
BUILD_IRQ(0x6d)
BUILD_IRQ(0x6e)
BUILD_IRQ(0x6f)
BUILD_IRQ(0x70)
#endif
/* Pointers to the low-level handlers. */
static void (*interrupt[NR_IRQS])(void) = {
static void (*interrupt[MACH_IRQS])(void) = {
IRQ0x31_interrupt, IRQ0x32_interrupt, IRQ0x33_interrupt,
IRQ0x34_interrupt, IRQ0x35_interrupt, IRQ0x36_interrupt,
IRQ0x37_interrupt, IRQ0x38_interrupt, IRQ0x39_interrupt,
@ -128,7 +176,20 @@ static void (*interrupt[NR_IRQS])(void) = {
IRQ0x46_interrupt, IRQ0x47_interrupt, IRQ0x48_interrupt,
IRQ0x49_interrupt, IRQ0x4a_interrupt, IRQ0x4b_interrupt,
IRQ0x4c_interrupt, IRQ0x4d_interrupt, IRQ0x4e_interrupt,
IRQ0x4f_interrupt
IRQ0x4f_interrupt, IRQ0x50_interrupt,
#if MACH_IRQS > 32
IRQ0x51_interrupt, IRQ0x52_interrupt, IRQ0x53_interrupt,
IRQ0x54_interrupt, IRQ0x55_interrupt, IRQ0x56_interrupt,
IRQ0x57_interrupt, IRQ0x58_interrupt, IRQ0x59_interrupt,
IRQ0x5a_interrupt, IRQ0x5b_interrupt, IRQ0x5c_interrupt,
IRQ0x5d_interrupt, IRQ0x5e_interrupt, IRQ0x5f_interrupt,
IRQ0x60_interrupt, IRQ0x61_interrupt, IRQ0x62_interrupt,
IRQ0x63_interrupt, IRQ0x64_interrupt, IRQ0x65_interrupt,
IRQ0x66_interrupt, IRQ0x67_interrupt, IRQ0x68_interrupt,
IRQ0x69_interrupt, IRQ0x6a_interrupt, IRQ0x6b_interrupt,
IRQ0x6c_interrupt, IRQ0x6d_interrupt, IRQ0x6e_interrupt,
IRQ0x6f_interrupt, IRQ0x70_interrupt,
#endif
};
void
@ -137,13 +198,26 @@ block_irq(int irq, int cpu)
int intr_mask;
unsigned long flags;
spin_lock_irqsave(&irq_lock, flags);
intr_mask = REG_RD_INT(intr_vect, irq_regs[cpu], rw_mask);
spin_lock_irqsave(&irq_lock, flags);
if (irq - FIRST_IRQ < 32)
intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu],
rw_mask, 0);
else
intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu],
rw_mask, 1);
/* Remember; 1 let through, 0 block. */
intr_mask &= ~(1 << (irq - FIRST_IRQ));
/* Remember; 1 let thru, 0 block. */
if (irq - FIRST_IRQ < 32)
intr_mask &= ~(1 << (irq - FIRST_IRQ));
else
intr_mask &= ~(1 << (irq - FIRST_IRQ - 32));
REG_WR_INT(intr_vect, irq_regs[cpu], rw_mask, intr_mask);
if (irq - FIRST_IRQ < 32)
REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask,
0, intr_mask);
else
REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask,
1, intr_mask);
spin_unlock_irqrestore(&irq_lock, flags);
}
@ -154,12 +228,26 @@ unblock_irq(int irq, int cpu)
unsigned long flags;
spin_lock_irqsave(&irq_lock, flags);
intr_mask = REG_RD_INT(intr_vect, irq_regs[cpu], rw_mask);
if (irq - FIRST_IRQ < 32)
intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu],
rw_mask, 0);
else
intr_mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu],
rw_mask, 1);
/* Remember; 1 let through, 0 block. */
intr_mask |= (1 << (irq - FIRST_IRQ));
/* Remember; 1 let thru, 0 block. */
if (irq - FIRST_IRQ < 32)
intr_mask |= (1 << (irq - FIRST_IRQ));
else
intr_mask |= (1 << (irq - FIRST_IRQ - 32));
if (irq - FIRST_IRQ < 32)
REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask,
0, intr_mask);
else
REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask,
1, intr_mask);
REG_WR_INT(intr_vect, irq_regs[cpu], rw_mask, intr_mask);
spin_unlock_irqrestore(&irq_lock, flags);
}
@ -298,8 +386,9 @@ crisv32_do_multiple(struct pt_regs* regs)
{
int cpu;
int mask;
int masked;
int masked[NBR_REGS];
int bit;
int i;
cpu = smp_processor_id();
@ -308,42 +397,59 @@ crisv32_do_multiple(struct pt_regs* regs)
*/
irq_enter();
/* Get which IRQs that happened. */
masked = REG_RD_INT(intr_vect, irq_regs[cpu], r_masked_vect);
for (i = 0; i < NBR_REGS; i++) {
/* Get which IRQs that happend. */
masked[i] = REG_RD_INT_VECT(intr_vect, irq_regs[cpu],
r_masked_vect, i);
/* Calculate new IRQ mask with these IRQs disabled. */
mask = REG_RD_INT(intr_vect, irq_regs[cpu], rw_mask);
mask &= ~masked;
/* Calculate new IRQ mask with these IRQs disabled. */
mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i);
mask &= ~masked[i];
/* Timer IRQ is never masked */
if (masked & TIMER_MASK)
mask |= TIMER_MASK;
/* Block all the IRQs */
REG_WR_INT(intr_vect, irq_regs[cpu], rw_mask, mask);
#ifdef TIMER_VECT1
if ((i == 1) && (masked[0] & TIMER_MASK))
mask |= TIMER_MASK;
#else
if ((i == 0) && (masked[0] & TIMER_MASK))
mask |= TIMER_MASK;
#endif
/* Block all the IRQs */
REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i, mask);
/* Check for timer IRQ and handle it special. */
if (masked & TIMER_MASK) {
masked &= ~TIMER_MASK;
do_IRQ(TIMER_INTR_VECT, regs);
#ifdef TIMER_VECT1
if ((i == 1) && (masked[i] & TIMER_MASK)) {
masked[i] &= ~TIMER_MASK;
do_IRQ(TIMER0_INTR_VECT, regs);
}
#else
if ((i == 0) && (masked[i] & TIMER_MASK)) {
masked[i] &= ~TIMER_MASK;
do_IRQ(TIMER0_INTR_VECT, regs);
}
}
#endif
#ifdef IGNORE_MASK
/* Remove IRQs that can't be handled as multiple. */
masked &= ~IGNORE_MASK;
masked[0] &= ~IGNORE_MASK;
#endif
/* Handle the rest of the IRQs. */
for (bit = 0; bit < 32; bit++)
{
if (masked & (1 << bit))
do_IRQ(bit + FIRST_IRQ, regs);
for (i = 0; i < NBR_REGS; i++) {
for (bit = 0; bit < 32; bit++) {
if (masked[i] & (1 << bit))
do_IRQ(bit + FIRST_IRQ + i*32, regs);
}
}
/* Unblock all the IRQs. */
mask = REG_RD_INT(intr_vect, irq_regs[cpu], rw_mask);
mask |= masked;
REG_WR_INT(intr_vect, irq_regs[cpu], rw_mask, mask);
for (i = 0; i < NBR_REGS; i++) {
mask = REG_RD_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i);
mask |= masked[i];
REG_WR_INT_VECT(intr_vect, irq_regs[cpu], rw_mask, i, mask);
}
/* This irq_exit() will trigger the soft IRQs. */
irq_exit();
@ -361,20 +467,21 @@ init_IRQ(void)
reg_intr_vect_rw_mask vect_mask = {0};
/* Clear all interrupts masks. */
REG_WR(intr_vect, regi_irq, rw_mask, vect_mask);
for (i = 0; i < NBR_REGS; i++)
REG_WR_VECT(intr_vect, regi_irq, rw_mask, i, vect_mask);
for (i = 0; i < 256; i++)
etrax_irv->v[i] = weird_irq;
/* Point all IRQs to bad handlers. */
/* Point all IRQ's to bad handlers. */
for (i = FIRST_IRQ, j = 0; j < NR_IRQS; i++, j++) {
irq_desc[j].chip = &crisv32_irq_type;
set_exception_vector(i, interrupt[j]);
}
/* Mark Timer and IPI IRQs as CPU local */
irq_allocations[TIMER_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED;
irq_desc[TIMER_INTR_VECT].status |= IRQ_PER_CPU;
irq_allocations[TIMER0_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED;
irq_desc[TIMER0_INTR_VECT].status |= IRQ_PER_CPU;
irq_allocations[IPI_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED;
irq_desc[IPI_INTR_VECT].status |= IRQ_PER_CPU;
@ -391,6 +498,11 @@ init_IRQ(void)
set_exception_vector(0x0a, d_mmu_access);
set_exception_vector(0x0b, d_mmu_write);
#ifdef CONFIG_BUG
/* Break 14 handler, used to implement cheap BUG(). */
set_exception_vector(0x1e, breakh_BUG);
#endif
/* The system-call trap is reached by "break 13". */
set_exception_vector(0x1d, system_call);