drivers: mfd: donot clear interrupt status
If there is a fake interrupt SW is clearing interrupt status, due to this some of the required interrupts are getting cleared. Remove clearing of status register to avoid this. CRs-Fixed: 2045773 Change-Id: I38247d69bd49a64731c3ec695d5470f5c591fea6 Signed-off-by: Yeleswarapu Nagaradhesh <nagaradh@codeaurora.org>
This commit is contained in:
parent
1ccabf65ac
commit
630630aa32
1 changed files with 25 additions and 5 deletions
|
@ -290,7 +290,7 @@ static irqreturn_t wcd9xxx_irq_thread(int irq, void *data)
|
|||
static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 1);
|
||||
struct wcd9xxx_core_resource *wcd9xxx_res = data;
|
||||
int num_irq_regs = wcd9xxx_res->num_irq_regs;
|
||||
u8 status[num_irq_regs], status1[num_irq_regs];
|
||||
u8 status[4], status1[4] = {0}, unmask_status[4] = {0};
|
||||
|
||||
if (unlikely(wcd9xxx_lock_sleep(wcd9xxx_res) == false)) {
|
||||
dev_err(wcd9xxx_res->dev, "Failed to hold suspend\n");
|
||||
|
@ -314,6 +314,23 @@ static irqreturn_t wcd9xxx_irq_thread(int irq, void *data)
|
|||
"Failed to read interrupt status: %d\n", ret);
|
||||
goto err_disable_irq;
|
||||
}
|
||||
/*
|
||||
* If status is 0 return without clearing.
|
||||
* status contains: HW status - masked interrupts
|
||||
* status1 contains: unhandled interrupts - masked interrupts
|
||||
* unmasked_status contains: unhandled interrupts
|
||||
*/
|
||||
if (unlikely(!memcmp(status, status1, sizeof(status)))) {
|
||||
pr_debug("%s: status is 0\n", __func__);
|
||||
wcd9xxx_unlock_sleep(wcd9xxx_res);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy status to unmask_status before masking, otherwise SW may miss
|
||||
* to clear masked interrupt in corner case.
|
||||
*/
|
||||
memcpy(unmask_status, status, sizeof(unmask_status));
|
||||
|
||||
/* Apply masking */
|
||||
for (i = 0; i < num_irq_regs; i++)
|
||||
|
@ -337,6 +354,8 @@ static irqreturn_t wcd9xxx_irq_thread(int irq, void *data)
|
|||
wcd9xxx_irq_dispatch(wcd9xxx_res, &irqdata);
|
||||
status1[BIT_BYTE(irqdata.intr_num)] &=
|
||||
~BYTE_BIT_MASK(irqdata.intr_num);
|
||||
unmask_status[BIT_BYTE(irqdata.intr_num)] &=
|
||||
~BYTE_BIT_MASK(irqdata.intr_num);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -358,12 +377,13 @@ static irqreturn_t wcd9xxx_irq_thread(int irq, void *data)
|
|||
linebuf, sizeof(linebuf), false);
|
||||
pr_warn("%s: status1 : %s\n", __func__, linebuf);
|
||||
}
|
||||
|
||||
memset(status, 0xff, num_irq_regs);
|
||||
|
||||
/*
|
||||
* unmask_status contains unhandled interrupts, hence clear all
|
||||
* unhandled interrupts.
|
||||
*/
|
||||
ret = regmap_bulk_write(wcd9xxx_res->wcd_core_regmap,
|
||||
wcd9xxx_res->intr_reg[WCD9XXX_INTR_CLEAR_BASE],
|
||||
status, num_irq_regs);
|
||||
unmask_status, num_irq_regs);
|
||||
if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
|
||||
regmap_write(wcd9xxx_res->wcd_core_regmap,
|
||||
wcd9xxx_res->intr_reg[WCD9XXX_INTR_CLR_COMMIT],
|
||||
|
|
Loading…
Add table
Reference in a new issue