From: Liu Ying Date: Wed, 19 Dec 2012 06:46:06 +0000 (+0800) Subject: ENGR00237678 IPUv3:Clean up sync and error interrupt X-Git-Tag: v3.0.35-fsl~185 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=bbbd1b6cafeb51d906de03335922f76b71452eff;p=karo-tx-linux.git ENGR00237678 IPUv3:Clean up sync and error interrupt 1) Split sync and error interrupt handler into 2 different handlers, so that we may save several CPU cycles to handler sync interrupt which is triggered in most IPU usecases. 2) So far, every IPUv3 version in different SoCs has sync and error interrupts, so we return -ENODEV if they cannot be gotten from platform resource. Then, we may request them directly but do not check more. 3) Clean up free irq code by removing unnecessary check. Signed-off-by: Liu Ying (cherry picked from commit a88d2aa8f89d868474e75ea46032f7c40c42c57b) --- diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c index 92703f34b6aa..ab54bdb757cb 100644 --- a/drivers/mxc/ipu3/ipu_common.c +++ b/drivers/mxc/ipu3/ipu_common.c @@ -44,7 +44,8 @@ static struct ipu_soc ipu_array[MXC_IPU_MAX_NUM]; int g_ipu_hw_rev; /* Static functions */ -static irqreturn_t ipu_irq_handler(int irq, void *desc); +static irqreturn_t ipu_sync_irq_handler(int irq, void *desc); +static irqreturn_t ipu_err_irq_handler(int irq, void *desc); static inline uint32_t channel_2_dma(ipu_channel_t ch, ipu_buffer_t type) { @@ -242,19 +243,17 @@ static int __devinit ipu_probe(struct platform_device *pdev) goto failed_get_res; } - if (request_irq(ipu->irq_sync, ipu_irq_handler, 0, pdev->name, ipu) != 0) { + ret = request_irq(ipu->irq_sync, ipu_sync_irq_handler, 0, + pdev->name, ipu); + if (ret) { dev_err(ipu->dev, "request SYNC interrupt failed\n"); - ret = -EBUSY; goto failed_req_irq_sync; } - /* Some platforms have 2 IPU interrupts */ - if (ipu->irq_err >= 0) { - if (request_irq - (ipu->irq_err, ipu_irq_handler, 0, pdev->name, ipu) != 0) { - dev_err(ipu->dev, "request ERR interrupt failed\n"); - ret = -EBUSY; - goto failed_req_irq_err; - } + ret = request_irq(ipu->irq_err, ipu_err_irq_handler, 0, + pdev->name, ipu); + if (ret) { + dev_err(ipu->dev, "request ERR interrupt failed\n"); + goto failed_req_irq_err; } ipu_base = res->start; @@ -368,8 +367,7 @@ failed_clk_setup: iounmap(ipu->disp_base[1]); iounmap(ipu->vdi_reg); failed_ioremap: - if (ipu->irq_sync) - free_irq(ipu->irq_err, ipu); + free_irq(ipu->irq_err, ipu); failed_req_irq_err: free_irq(ipu->irq_sync, ipu); failed_req_irq_sync: @@ -383,10 +381,8 @@ int __devexit ipu_remove(struct platform_device *pdev) unregister_ipu_device(ipu, pdev->id); - if (ipu->irq_sync) - free_irq(ipu->irq_sync, ipu); - if (ipu->irq_err) - free_irq(ipu->irq_err, ipu); + free_irq(ipu->irq_sync, ipu); + free_irq(ipu->irq_err, ipu); clk_put(ipu->ipu_clk); @@ -2371,42 +2367,17 @@ int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi) } EXPORT_SYMBOL(ipu_disable_csi); -static irqreturn_t ipu_irq_handler(int irq, void *desc) +static irqreturn_t ipu_sync_irq_handler(int irq, void *desc) { struct ipu_soc *ipu = desc; int i; - uint32_t line; - uint32_t bit; + uint32_t line, bit, int_stat, int_ctrl; 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 }; spin_lock(&ipu->int_reg_spin_lock); - for (i = 0;; i++) { - if (err_reg[i] == 0) - break; - - int_stat = ipu_cm_read(ipu, IPU_INT_STAT(err_reg[i])); - int_stat &= ipu_cm_read(ipu, IPU_INT_CTRL(err_reg[i])); - if (int_stat) { - ipu_cm_write(ipu, int_stat, IPU_INT_STAT(err_reg[i])); - dev_warn(ipu->dev, - "IPU Warning - IPU_INT_STAT_%d = 0x%08X\n", - err_reg[i], int_stat); - /* Disable interrupts so we only get error once */ - int_stat = - ipu_cm_read(ipu, IPU_INT_CTRL(err_reg[i])) & ~int_stat; - ipu_cm_write(ipu, int_stat, IPU_INT_CTRL(err_reg[i])); - } - } - - for (i = 0;; i++) { - if (int_reg[i] == 0) - break; - + for (i = 0; int_reg[i] != 0; i++) { int_stat = ipu_cm_read(ipu, IPU_INT_STAT(int_reg[i])); int_ctrl = ipu_cm_read(ipu, IPU_INT_CTRL(int_reg[i])); int_stat &= int_ctrl; @@ -2432,6 +2403,35 @@ static irqreturn_t ipu_irq_handler(int irq, void *desc) return result; } +static irqreturn_t ipu_err_irq_handler(int irq, void *desc) +{ + struct ipu_soc *ipu = desc; + int i; + uint32_t int_stat; + const int err_reg[] = { 5, 6, 9, 10, 0 }; + + spin_lock(&ipu->int_reg_spin_lock); + + for (i = 0; err_reg[i] != 0; i++) { + int_stat = ipu_cm_read(ipu, IPU_INT_STAT(err_reg[i])); + int_stat &= ipu_cm_read(ipu, IPU_INT_CTRL(err_reg[i])); + if (int_stat) { + ipu_cm_write(ipu, int_stat, IPU_INT_STAT(err_reg[i])); + dev_warn(ipu->dev, + "IPU Warning - IPU_INT_STAT_%d = 0x%08X\n", + err_reg[i], int_stat); + /* Disable interrupts so we only get error once */ + int_stat = ipu_cm_read(ipu, IPU_INT_CTRL(err_reg[i])) & + ~int_stat; + ipu_cm_write(ipu, int_stat, IPU_INT_CTRL(err_reg[i])); + } + } + + spin_unlock(&ipu->int_reg_spin_lock); + + return IRQ_HANDLED; +} + /*! * This function enables the interrupt for the specified interrupt line. * The interrupt lines are defined in \b ipu_irq_line enum.