From 1fa08ac276c3414dfb8ea318b56aa2de786c8a97 Mon Sep 17 00:00:00 2001 From: Wayne Zou Date: Tue, 12 Jun 2012 14:45:52 +0800 Subject: [PATCH] ENGR00213158-2 IPU: Add IPU oneshot interrupt mode Add IPU oneshot interrupt mode: IPU_IRQF_ONESHOT. Interrupt is not reenabled after irq handler finished. Signed-off-by: Wayne Zou --- drivers/mxc/ipu3/ipu_common.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c index 7682b47fc66c..b1fb4ca63474 100644 --- a/drivers/mxc/ipu3/ipu_common.c +++ b/drivers/mxc/ipu3/ipu_common.c @@ -2547,11 +2547,14 @@ static irqreturn_t ipu_irq_handler(int irq, void *desc) 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) @@ -2580,18 +2583,30 @@ static irqreturn_t ipu_irq_handler(int irq, void *desc) 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; @@ -2792,7 +2807,7 @@ void ipu_free_irq(struct ipu_soc *ipu, uint32_t irq, void *dev_id) 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); -- 2.39.5