static int icu_get_irq(unsigned int irq) { uint16_t pend1, pend2; uint16_t mask1, mask2; int i; pend1 = icu1_read(SYSINT1REG); mask1 = icu1_read(MSYSINT1REG); pend2 = icu2_read(SYSINT2REG); mask2 = icu2_read(MSYSINT2REG); mask1 &= pend1; mask2 &= pend2; if (mask1) { for (i = 0; i < 16; i++) { if (irq == INT_TO_IRQ(sysint1_assign[i]) && (mask1 & (1 << i))) return SYSINT1_IRQ(i); } } if (mask2) { for (i = 0; i < 16; i++) { if (irq == INT_TO_IRQ(sysint2_assign[i]) && (mask2 & (1 << i))) return SYSINT2_IRQ(i); } } printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2); atomic_inc(&irq_err_count); return -1; }
static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) { struct irq_desc *desc = irq_desc + irq; uint16_t intassign0, intassign1; unsigned int pin; pin = SYSINT1_IRQ_TO_PIN(irq); spin_lock_irq(&desc->lock); intassign0 = icu1_read(INTASSIGN0); intassign1 = icu1_read(INTASSIGN1); switch (pin) { case 0: intassign0 &= ~INTASSIGN_MASK; intassign0 |= (uint16_t)assign; break; case 1: intassign0 &= ~(INTASSIGN_MASK << 3); intassign0 |= (uint16_t)assign << 3; break; case 2: intassign0 &= ~(INTASSIGN_MASK << 6); intassign0 |= (uint16_t)assign << 6; break; case 3: intassign0 &= ~(INTASSIGN_MASK << 9); intassign0 |= (uint16_t)assign << 9; break; case 8: intassign0 &= ~(INTASSIGN_MASK << 12); intassign0 |= (uint16_t)assign << 12; break; case 9: intassign1 &= ~INTASSIGN_MASK; intassign1 |= (uint16_t)assign; break; case 11: intassign1 &= ~(INTASSIGN_MASK << 6); intassign1 |= (uint16_t)assign << 6; break; case 12: intassign1 &= ~(INTASSIGN_MASK << 9); intassign1 |= (uint16_t)assign << 9; break; default: spin_unlock_irq(&desc->lock); return -EINVAL; } sysint1_assign[pin] = assign; icu1_write(INTASSIGN0, intassign0); icu1_write(INTASSIGN1, intassign1); spin_unlock_irq(&desc->lock); return 0; }
static inline uint16_t icu1_clear(uint8_t offset, uint16_t clear) { uint16_t data; data = icu1_read(offset); data &= ~clear; icu1_write(offset, data); return data; }
static inline uint16_t icu1_set(uint8_t offset, uint16_t set) { uint16_t data; data = icu1_read(offset); data |= set; icu1_write(offset, data); return data; }
static inline int set_sysint2_assign(unsigned int irq, unsigned char assign) { struct irq_desc *desc = irq_desc + irq; uint16_t intassign2, intassign3; unsigned int pin; pin = SYSINT2_IRQ_TO_PIN(irq); spin_lock_irq(&desc->lock); intassign2 = icu1_read(INTASSIGN2); intassign3 = icu1_read(INTASSIGN3); switch (pin) { case 0: intassign2 &= ~INTASSIGN_MASK; intassign2 |= (uint16_t)assign; break; case 1: intassign2 &= ~(INTASSIGN_MASK << 3); intassign2 |= (uint16_t)assign << 3; break; case 3: intassign2 &= ~(INTASSIGN_MASK << 6); intassign2 |= (uint16_t)assign << 6; break; case 4: intassign2 &= ~(INTASSIGN_MASK << 9); intassign2 |= (uint16_t)assign << 9; break; case 5: intassign2 &= ~(INTASSIGN_MASK << 12); intassign2 |= (uint16_t)assign << 12; break; case 6: intassign3 &= ~INTASSIGN_MASK; intassign3 |= (uint16_t)assign; break; case 7: intassign3 &= ~(INTASSIGN_MASK << 3); intassign3 |= (uint16_t)assign << 3; break; case 8: intassign3 &= ~(INTASSIGN_MASK << 6); intassign3 |= (uint16_t)assign << 6; break; case 9: intassign3 &= ~(INTASSIGN_MASK << 9); intassign3 |= (uint16_t)assign << 9; break; case 10: intassign3 &= ~(INTASSIGN_MASK << 12); intassign3 |= (uint16_t)assign << 12; break; default: return -EINVAL; } sysint2_assign[pin] = assign; icu1_write(INTASSIGN2, intassign2); icu1_write(INTASSIGN3, intassign3); spin_unlock_irq(&desc->lock); return 0; }