summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Kuo <stevek@nvidia.com>2012-03-30 15:00:38 +0800
committerVarun Colbert <vcolbert@nvidia.com>2012-05-03 19:25:01 -0700
commitd5252b48f3c2c0a4be383311cae25752bcdc07b7 (patch)
tree6532ed16cadbd234cb38628876bf4896898eaf99
parentf16614d48a3025789df16d1d060efd581933f198 (diff)
mfd: tps80031: fix missed irq issue
We found missed irq could be happened if clear all INT_STS_x register in one time. Shadow register pushes the irq status after the first byte of INT_STS_x was cleared The proposed way to clear interrupt is to write only one INT_STS_x register. It will also clear the other two ones. Bug 952476 Reviewed-on: http://git-master/r/93453 Signed-off-by: Steve Kuo <stevek@nvidia.com> (cherry picked from commit 0c92f32e9e03defaeac991518b26134e59ef4db6) Change-Id: I76179be4847f59a1687926b9b0dde6ebd3f58aa4 Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-on: http://git-master/r/100306
-rw-r--r--drivers/mfd/tps80031.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c
index e8ea75c424c6..94ba777bcdb3 100644
--- a/drivers/mfd/tps80031.c
+++ b/drivers/mfd/tps80031.c
@@ -874,8 +874,22 @@ static irqreturn_t tps80031_irq(int irq, void *data)
acks = (tmp[2] << 16) | (tmp[1] << 8) | tmp[0];
if (acks) {
- ret = tps80031_writes(tps80031->dev, SLAVE_ID2,
- TPS80031_INT_STS_A, 3, tmp);
+ /*
+ * Hardware behavior: hardware have the shadow register for
+ * interrupt status register which is updated if interrupt
+ * comes just after the interrupt status read. This shadow
+ * register gets written to main status register and cleared
+ * if any byte write happens in any of status register like
+ * STS_A, STS_B or STS_C.
+ * Hence here to clear the original interrupt status and
+ * updating the STS register with the shadow register, it is
+ * require to write only one byte in any of STS register.
+ * Having multiple register write can cause the STS register
+ * to clear without handling those interrupt and can cause
+ * interrupt miss.
+ */
+ ret = tps80031_write(tps80031->dev, SLAVE_ID2,
+ TPS80031_INT_STS_A, 0);
if (ret < 0) {
dev_err(tps80031->dev, "failed to write "
"interrupt status\n");