/* CRIME 1.1 appears to deliver all interrupts to this one pin. */ void ip32_irq0(struct pt_regs *regs) { u64 crime_int; u64 crime_mask; int irq = 0; unsigned long flags; save_and_cli (flags); /* disable crime interrupts */ crime_mask = crime_read_64(CRIME_INT_MASK); crime_write_64(CRIME_INT_MASK, 0); crime_int = crime_read_64(CRIME_INT_STAT); if (crime_int & CRIME_MACE_INT_MASK) { crime_int &= CRIME_MACE_INT_MASK; irq = ffs (crime_int); } else if (crime_int & CRIME_MACEISA_INT_MASK) { u32 mace_int; mace_int = mace_read_32 (MACEISA_INT_STAT); if (mace_int == 0) irq = 0; else irq = ffs (mace_int) + 32; } else if (crime_int & CRIME_MACEPCI_INT_MASK) { crime_int &= CRIME_MACEPCI_INT_MASK; crime_int >>= 8; irq = ffs (crime_int) + 8; } else if (crime_int & 0xffff0000) {
void __init ip32_timer_setup (struct irqaction *irq) { u64 crime_time; u32 cc_tick; write_c0_count(0); irq->handler = cc_timer_interrupt; printk("Calibrating system timer... "); crime_time = crime_read_64(CRIME_TIME) & CRIME_TIME_MASK; cc_tick = read_c0_count(); while ((crime_read_64 (CRIME_TIME) & CRIME_TIME_MASK) - crime_time < WAIT_MS * 1000000 / CRIME_NS_PER_TICK) ; cc_tick = read_c0_count() - cc_tick; cc_interval = cc_tick / HZ * (1000 / WAIT_MS); /* * The round-off seems unnecessary; in testing, the error of the * above procedure is < 100 ticks, which means it gets filtered * out by the HZ adjustment. */ cc_interval = (cc_interval / PER_MHZ) * PER_MHZ; printk("%d MHz CPU detected\n", (int) (cc_interval / PER_MHZ)); setup_irq (CLOCK_IRQ, irq); #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) /* Set ourselves up for future interrupts */ write_c0_compare(read_c0_count() + cc_interval); change_c0_status(ST0_IM, ALLINTS); local_irq_enable(); }
static void ip32_unknown_interrupt (struct pt_regs *regs) { u64 crime; u32 mace; printk ("Unknown interrupt occurred!\n"); printk ("cp0_status: %08x\tcp0_cause: %08x\n", read_32bit_cp0_register (CP0_STATUS), read_32bit_cp0_register (CP0_CAUSE)); crime = crime_read_64 (CRIME_INT_MASK); printk ("CRIME interrupt mask: %016lx\n", crime); crime = crime_read_64 (CRIME_INT_STAT); printk ("CRIME interrupt status: %016lx\n", crime); crime = crime_read_64 (CRIME_HARD_INT); printk ("CRIME hardware interrupt register: %016lx\n", crime); mace = mace_read_32 (MACEISA_INT_MASK); printk ("MACE ISA interrupt mask: %08x\n", mace); mace = mace_read_32 (MACEISA_INT_STAT); printk ("MACE ISA interrupt status: %08x\n", mace); mace = mace_read_32 (MACEPCI_CONTROL); printk ("MACE PCI control register: %08x\n", mace); printk("Register dump:\n"); show_regs(regs); printk("Please mail this report to [email protected]\n"); printk("Spinning..."); while(1) ; }
static void enable_maceisa_irq (unsigned int irq) { u64 crime_mask; u32 mace_mask; unsigned int crime_int = 0; unsigned long flags; DBG ("maceisa enable: %u\n", irq); switch (irq) { case MACEISA_AUDIO_SW_IRQ ... MACEISA_AUDIO3_MERR_IRQ: crime_int = MACE_AUDIO_INT; break; case MACEISA_RTC_IRQ ... MACEISA_TIMER2_IRQ: crime_int = MACE_MISC_INT; break; case MACEISA_PARALLEL_IRQ ... MACEISA_SERIAL2_RDMAOR_IRQ: crime_int = MACE_SUPERIO_INT; break; } DBG ("crime_int %016lx enabled\n", crime_int); save_and_cli(flags); crime_mask = crime_read_64(CRIME_INT_MASK); crime_mask |= crime_int; crime_write_64(CRIME_INT_MASK, crime_mask); mace_mask = mace_read_32(MACEISA_INT_MASK); mace_mask |= 1 << (irq - 33); mace_write_32(MACEISA_INT_MASK, mace_mask); restore_flags(flags); }
static void disable_mace_irq(unsigned int irq) { u64 crime_mask; unsigned long flags; save_and_cli (flags); crime_mask = crime_read_64 (CRIME_INT_MASK); crime_mask &= ~(1 << (irq - 1)); crime_write_64 (CRIME_INT_MASK, crime_mask); restore_flags(flags); }
static void mask_and_ack_crime_irq (unsigned int irq) { u64 crime_mask; unsigned long flags; /* Edge triggered interrupts must be cleared. */ if ((irq >= CRIME_GBE0_IRQ && irq <= CRIME_GBE3_IRQ) || (irq >= CRIME_RE_EMPTY_E_IRQ && irq <= CRIME_RE_IDLE_E_IRQ) || (irq >= CRIME_SOFT0_IRQ && irq <= CRIME_SOFT2_IRQ)) { save_and_cli(flags); crime_mask = crime_read_64(CRIME_HARD_INT); crime_mask &= ~(1 << (irq - 1)); crime_write_64(CRIME_HARD_INT, crime_mask); restore_flags(flags); } disable_crime_irq(irq); }
static void enable_macepci_irq(unsigned int irq) { u32 mace_mask; u64 crime_mask; unsigned long flags; save_and_cli(flags); mace_mask = mace_read_32(MACEPCI_CONTROL); mace_mask |= MACEPCI_CONTROL_INT(irq - 9); mace_write_32(MACEPCI_CONTROL, mace_mask); /* * In case the CRIME interrupt isn't enabled, we must enable it; * however, we never disable interrupts at that level. */ crime_mask = crime_read_64(CRIME_INT_MASK); crime_mask |= 1 << (irq - 1); crime_write_64(CRIME_INT_MASK, crime_mask); restore_flags(flags); }