struct ipu_soc *ipu = desc;
int i;
uint32_t line;
+ uint32_t bit;
irqreturn_t result = IRQ_NONE;
uint32_t int_stat;
+ uint32_t int_ctrl;
const int err_reg[] = { 5, 6, 9, 10, 0 };
const int int_reg[] = { 1, 2, 3, 4, 11, 12, 13, 14, 15, 0 };
unsigned long lock_flags;
+ uint32_t oneshot;
for (i = 0;; i++) {
if (err_reg[i] == 0)
break;
spin_lock_irqsave(&ipu->spin_lock, lock_flags);
int_stat = ipu_cm_read(ipu, IPU_INT_STAT(int_reg[i]));
- int_stat &= ipu_cm_read(ipu, IPU_INT_CTRL(int_reg[i]));
+ int_ctrl = ipu_cm_read(ipu, IPU_INT_CTRL(int_reg[i]));
+ int_stat &= int_ctrl;
ipu_cm_write(ipu, int_stat, IPU_INT_STAT(int_reg[i]));
spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+ oneshot = 0;
while ((line = ffs(int_stat)) != 0) {
- line--;
+ bit = --line;
int_stat &= ~(1UL << line);
line += (int_reg[i] - 1) * 32;
+ if (ipu->irq_list[line].flags & IPU_IRQF_ONESHOT)
+ oneshot |= 1UL << bit;
result |=
ipu->irq_list[line].handler(line,
ipu->irq_list[line].
dev_id);
}
+ if (oneshot) {
+ spin_lock_irqsave(&ipu->spin_lock, lock_flags);
+ if ((~int_ctrl) & oneshot)
+ BUG();
+ int_ctrl &= ~oneshot;
+ ipu_cm_write(ipu, int_ctrl, IPU_INT_CTRL(int_reg[i]));
+ spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+ }
}
return result;
reg &= ~IPUIRQ_2_MASK(irq);
ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
if (ipu->irq_list[irq].dev_id == dev_id)
- ipu->irq_list[irq].handler = NULL;
+ memset(&ipu->irq_list[irq], 0, sizeof(ipu->irq_list[irq]));
spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);