diff options
author | David Schalig <dschalig@nvidia.com> | 2011-12-14 16:01:30 +0900 |
---|---|---|
committer | Varun Wadekar <vwadekar@nvidia.com> | 2011-12-22 11:32:03 +0530 |
commit | 1cdb02ea9f18af3a810d50fe1370bd744fe37537 (patch) | |
tree | 7e37e3b215c6cdb646af164c85679b9e43809023 /drivers/mfd | |
parent | 51a3974d0c5272ce8ab48d3370dd3debe76747e8 (diff) |
mfd: tps80031: fix irq status clear sequence
According to tps80031 datasheet, all 3 interrupt status registers should
be read, before writing to clear them. The old code used interleaved status
read/clear, which may drop interrupts.
Bug 914740
Change-Id: I4c9c0b7c623ea0fe01d90e9a531ff2e9d34f125c
Signed-off-by: David Schalig <dschalig@nvidia.com>
Reviewed-on: http://git-master/r/69941
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/tps80031.c | 42 |
1 files changed, 21 insertions, 21 deletions
diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c index 6fe80dc51931..e6bfd475f668 100644 --- a/drivers/mfd/tps80031.c +++ b/drivers/mfd/tps80031.c @@ -801,35 +801,35 @@ static irqreturn_t tps80031_irq(int irq, void *data) { struct tps80031 *tps80031 = data; int ret = 0; - u8 tmp[3]; u32 acks; int i; + uint8_t tmp[3]; - for (i = 0; i < 3; i++) { - ret = tps80031_read(tps80031->dev, SLAVE_ID2, - TPS80031_INT_STS_A + i, &tmp[i]); + ret = tps80031_reads(tps80031->dev, SLAVE_ID2, + TPS80031_INT_STS_A, 3, tmp); + if (ret < 0) { + dev_err(tps80031->dev, "failed to read interrupt status\n"); + return IRQ_NONE; + } + acks = (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]; + + if (acks) { + ret = tps80031_writes(tps80031->dev, SLAVE_ID2, + TPS80031_INT_STS_A, 3, tmp); if (ret < 0) { - dev_err(tps80031->dev, "failed to read interrupt " - "status\n"); + dev_err(tps80031->dev, "failed to write " + "interrupt status\n"); return IRQ_NONE; } - if (tmp[i]) { - ret = tps80031_write(tps80031->dev, SLAVE_ID2, - TPS80031_INT_STS_A + i, tmp[i]); - if (ret < 0) { - dev_err(tps80031->dev, "failed to write " - "interrupt status\n"); - return IRQ_NONE; - } + + while (acks) { + i = __ffs(acks); + if (tps80031->irq_en & (1 << i)) + handle_nested_irq(tps80031->irq_base + i); + acks &= ~(1 << i); } } - acks = (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]; - while (acks) { - i = __ffs(acks); - if (tps80031->irq_en & (1 << i)) - handle_nested_irq(tps80031->irq_base + i); - acks &= ~(1 << i); - } + return IRQ_HANDLED; } |