summaryrefslogtreecommitdiff
path: root/drivers/rtc/rtc-imxdi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-imxdi.c')
-rw-r--r--drivers/rtc/rtc-imxdi.c50
1 files changed, 31 insertions, 19 deletions
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c
index 063963736790..b54fb638c840 100644
--- a/drivers/rtc/rtc-imxdi.c
+++ b/drivers/rtc/rtc-imxdi.c
@@ -342,30 +342,42 @@ static irqreturn_t dryice_norm_irq(int irq, void *dev_id)
u32 dsr, dier;
irqreturn_t rc = IRQ_NONE;
- /* DSR_WCF clears itself on DSR read */
- dsr = di_read(pdata, DSR);
dier = di_read(pdata, DIER);
/* handle write complete and write error cases */
- if ((dier & DIER_WCIE) && (dsr & (DSR_WCF | DSR_WEF))) {
- /* mask the interrupt */
- di_int_disable(pdata, DIER_WCIE);
-
- /* save the dsr value for the wait queue */
- pdata->dsr |= dsr;
-
- wake_up_interruptible(&pdata->write_wait);
- rc = IRQ_HANDLED;
+ if ((dier & DIER_WCIE)) {
+ /*If the write wait queue is empty then there is no pending
+ operations. It means the interrupt is for DryIce -Security.
+ IRQ must be returned as none.*/
+ if (list_empty_careful(&pdata->write_wait.task_list))
+ return rc;
+
+ /* DSR_WCF clears itself on DSR read */
+ dsr = di_read(pdata, DSR);
+ if ((dsr & (DSR_WCF | DSR_WEF))) {
+ /* mask the interrupt */
+ di_int_disable(pdata, DIER_WCIE);
+
+ /* save the dsr value for the wait queue */
+ pdata->dsr |= dsr;
+
+ wake_up_interruptible(&pdata->write_wait);
+ rc = IRQ_HANDLED;
+ }
}
/* handle the alarm case */
- if ((dier & DIER_CAIE) && (dsr & DSR_CAF)) {
- /* mask the interrupt */
- di_int_disable(pdata, DIER_CAIE);
-
- /* finish alarm in user context */
- schedule_work(&pdata->work);
- rc = IRQ_HANDLED;
+ if ((dier & DIER_CAIE)) {
+ /* DSR_WCF clears itself on DSR read */
+ dsr = di_read(pdata, DSR);
+ if (dsr & DSR_CAF) {
+ /* mask the interrupt */
+ di_int_disable(pdata, DIER_CAIE);
+
+ /* finish alarm in user context */
+ schedule_work(&pdata->work);
+ rc = IRQ_HANDLED;
+ }
}
return rc;
}
@@ -440,7 +452,7 @@ static int dryice_rtc_probe(struct platform_device *pdev)
clk_enable(pdata->clk);
if (pdata->irq >= 0) {
- if (request_irq(pdata->irq, dryice_norm_irq, IRQF_DISABLED,
+ if (request_irq(pdata->irq, dryice_norm_irq, IRQF_SHARED,
pdev->name, pdata) < 0) {
dev_warn(&pdev->dev, "interrupt not available.\n");
pdata->irq = -1;