/* * $Id: tairqc.c,v 1.5 2007/11/02 13:27:42 init Exp $ */ #include #include #include #include #include #include #include #define TAIRQC_DEBUG #ifdef TAIRQC_DEBUG #define DPRINTF(x...) do { printf(x); } while (0) #else #define DPRINTF(x...) { } #endif /* * testarm Interrupt Controller Unit support. */ int tairqc_attach(struct device *self, uint32_t loc, uint8_t flags); void tairqc_mask_intr(uint8_t intrno); void tairqc_unmask_intr(uint8_t intrno); uint32_t tairqc_intrstatus(void); void tairqc_irq(void); extern void (*irq_trampoline_func)(void); struct tairqc_dd *irqcdd; /* current irq device */ struct driver tairqc_dr = { sizeof(struct tairqc_dd), tairqc_attach, NULL, NULL }; int tairqc_attach(struct device *self, uint32_t loc, uint8_t flags) { struct tairqc_dd *ddp = self->dv_devdata; /* leap to parent's bus_handle */ ddp->td_bushandlep = self->dv_parent->dv_aux; /* save locator */ ddp->td_ioaddr = loc ? loc : TAIRQC_REG_BASE; irqcdd = ddp; printf("testarm IRQ Controller (2=cons, 3=ether, 4=rtc, 6=mp)\n"); /* override trampoline so core irq jumps to us */ irq_trampoline_func = tairqc_irq; /* XXX unmask rtc intr */ tairqc_unmask_intr(4); return(0); } void tairqc_mask_intr(uint8_t intrno) { bus_write_1(irqcdd->td_bushandlep, irqcdd->td_ioaddr + TAIRQC_OFF_IRQMASK, intrno); DPRINTF("tairqc_mask_intr: masked interrupt no. %d (status=0x%x)\n", intrno, tairqc_intrstatus()); } void tairqc_unmask_intr(uint8_t intrno) { bus_write_1(irqcdd->td_bushandlep, irqcdd->td_ioaddr + TAIRQC_OFF_IRQUNMASK, intrno); DPRINTF("tairqc_unmask_intr: unmasked interrupt no. %d (status=0x%x)\n", intrno, tairqc_intrstatus()); } uint32_t tairqc_intrstatus(void) { bus_read_4(irqcdd->td_bushandlep, irqcdd->td_ioaddr + TAIRQC_OFF_IRQSTATUS); } void tairqc_irq(void) { /* * Process an IRQ. */ uint32_t irqstatus; /* read intr status; one bit per intr source */ irqstatus = tairqc_intrstatus(); DPRINTF("tairqc_itq: got interrupt (status=0x%x)\n", irqstatus); }