From 849c86ec97115425cb52b27cb260c7a32d935f0b Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Mon, 27 Jun 2016 16:42:13 +0800 Subject: MLK-12928-21 power: pf1550: fix charger interrupt never caught Charger interrupt can't be caught anymore after plug in DC 5V in/out dozens of times, that caused by VBUS_I or CHG_I pending interrupt not cleared in time. The root cause is VBUS_I and CHG_I will be triggered in very narrow window, and VBUS_I/CHG_I act as the sub-interrupt of charger and share the same interrupt handler. Thus if CHG_I interrupt status is coming while VBUS_I handler is running, CHG_I interrupt status will never be cleared, since interrupt has been disabled in ISR. The unclear CHG_I interrupt status make pf1550 never trigger next interrupt again. So clear all charger interrupt status in ISR to workaround instead of ack for every sub-intterrupt. Signed-off-by: Robin Gong --- drivers/power/supply/pf1550_charger.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/power') diff --git a/drivers/power/supply/pf1550_charger.c b/drivers/power/supply/pf1550_charger.c index fc7c5b9a54ad..d14ef2b29ffd 100644 --- a/drivers/power/supply/pf1550_charger.c +++ b/drivers/power/supply/pf1550_charger.c @@ -321,6 +321,7 @@ static void pf1550_charger_irq_work(struct work_struct *work) struct pf1550_charger, irq_work); int i, irq_type = -1; + unsigned int status; if (!chg->charger) return; @@ -351,6 +352,11 @@ static void pf1550_charger_irq_work(struct work_struct *work) dev_err(chg->dev, "unknown interrupt occurred.\n"); } + if (regmap_read(chg->pf1550->regmap, PF1550_CHARG_REG_CHG_INT, &status)) + dev_err(chg->dev, "Read CHG_INT error.\n"); + if (regmap_write(chg->pf1550->regmap, PF1550_CHARG_REG_CHG_INT, status)) + dev_err(chg->dev, "clear CHG_INT error.\n"); + mutex_unlock(&chg->mutex); } @@ -492,9 +498,9 @@ static int pf1550_reg_init(struct pf1550_charger *chg) int ret; unsigned int data; - /* Unmask charger interrupt */ + /* Unmask charger interrupt, mask DPMI and reserved bit */ ret = regmap_write(chg->pf1550->regmap, PF1550_CHARG_REG_CHG_INT_MASK, - 0x11); + 0x51); if (ret) { dev_err(chg->dev, "Error unmask charger interrupt: %d\n", ret); return ret; -- cgit v1.2.3