diff options
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/supply/bq24190_charger.c | 62 |
1 files changed, 52 insertions, 10 deletions
diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index a4f08492abeb..deb56f31c7a0 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -155,6 +155,8 @@ struct bq24190_dev_info { kernel_ulong_t model; unsigned int gpio_int; unsigned int irq; + bool initialized; + bool irq_event; struct mutex f_reg_lock; u8 f_reg; u8 ss_reg; @@ -1157,9 +1159,8 @@ static const struct power_supply_desc bq24190_battery_desc = { .property_is_writeable = bq24190_battery_property_is_writeable, }; -static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) +static void bq24190_check_status(struct bq24190_dev_info *bdi) { - struct bq24190_dev_info *bdi = data; const u8 battery_mask_ss = BQ24190_REG_SS_CHRG_STAT_MASK; const u8 battery_mask_f = BQ24190_REG_F_BAT_FAULT_MASK | BQ24190_REG_F_NTC_FAULT_MASK; @@ -1167,12 +1168,10 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) u8 ss_reg = 0, f_reg = 0; int i, ret; - pm_runtime_get_sync(bdi->dev); - ret = bq24190_read(bdi, BQ24190_REG_SS, &ss_reg); if (ret < 0) { dev_err(bdi->dev, "Can't read SS reg: %d\n", ret); - goto out; + return; } i = 0; @@ -1180,7 +1179,7 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) ret = bq24190_read(bdi, BQ24190_REG_F, &f_reg); if (ret < 0) { dev_err(bdi->dev, "Can't read F reg: %d\n", ret); - goto out; + return; } } while (f_reg && ++i < 2); @@ -1229,10 +1228,18 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) if (alert_battery) power_supply_changed(bdi->battery); -out: - pm_runtime_put_sync(bdi->dev); - dev_dbg(bdi->dev, "ss_reg: 0x%02x, f_reg: 0x%02x\n", ss_reg, f_reg); +} + +static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) +{ + struct bq24190_dev_info *bdi = data; + + bdi->irq_event = true; + pm_runtime_get_sync(bdi->dev); + bq24190_check_status(bdi); + pm_runtime_put_sync(bdi->dev); + bdi->irq_event = false; return IRQ_HANDLED; } @@ -1391,6 +1398,8 @@ static int bq24190_probe(struct i2c_client *client, goto out3; } + bdi->initialized = true; + ret = devm_request_threaded_irq(dev, bdi->irq, NULL, bq24190_irq_handler_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, @@ -1437,6 +1446,35 @@ static int bq24190_remove(struct i2c_client *client) return 0; } +static int bq24190_runtime_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct bq24190_dev_info *bdi = i2c_get_clientdata(client); + + if (!bdi->initialized) + return 0; + + dev_dbg(bdi->dev, "%s\n", __func__); + + return 0; +} + +static int bq24190_runtime_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct bq24190_dev_info *bdi = i2c_get_clientdata(client); + + if (!bdi->initialized) + return 0; + + if (!bdi->irq_event) { + dev_dbg(bdi->dev, "checking events on possible wakeirq\n"); + bq24190_check_status(bdi); + } + + return 0; +} + #ifdef CONFIG_PM_SLEEP static int bq24190_pm_suspend(struct device *dev) { @@ -1472,7 +1510,11 @@ static int bq24190_pm_resume(struct device *dev) } #endif -static SIMPLE_DEV_PM_OPS(bq24190_pm_ops, bq24190_pm_suspend, bq24190_pm_resume); +static const struct dev_pm_ops bq24190_pm_ops = { + SET_RUNTIME_PM_OPS(bq24190_runtime_suspend, bq24190_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(bq24190_pm_suspend, bq24190_pm_resume) +}; /* * Only support the bq24190 right now. The bq24192, bq24192i, and bq24193 |