diff options
Diffstat (limited to 'drivers/power/bq27x00_battery.c')
| -rw-r--r-- | drivers/power/bq27x00_battery.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 7bed61e6229..c10f48b20c8 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c @@ -37,8 +37,11 @@ #include <linux/power_supply.h> #include <linux/idr.h> #include <linux/i2c.h> +#include <linux/irq.h> +#include <linux/interrupt.h> #include <linux/slab.h> #include <asm/unaligned.h> +#include <linux/wakelock.h> #include <linux/power/bq27x00_battery.h> @@ -67,6 +70,8 @@ enum bq27xxx_reg_index { NUM_REGS }; +struct wake_lock chg_wake_lock; + /* bq27500 registers */ static __initdata u8 bq27500_regs[NUM_REGS] = { 0x00, /* CONTROL */ @@ -279,6 +284,7 @@ struct bq27x00_device_info { struct device *dev; int id; enum bq27x00_chip chip; + int irq; struct bq27x00_reg_cache cache; int charge_design_full; @@ -1345,6 +1351,16 @@ static void bq27x00_external_power_changed(struct power_supply *psy) schedule_delayed_work(&di->work, 0); } +static irqreturn_t bq27x00_chg_isr(int irq, void *dev) { + + struct power_supply *ps = (struct power_supply*) dev; + wake_lock_timeout(&chg_wake_lock, msecs_to_jiffies(500)); + dev_dbg(ps->dev, "%s: Updating battery status\n", __func__); + bq27x00_external_power_changed(ps); + + return IRQ_HANDLED; +} + static void __init set_properties_array(struct bq27x00_device_info *di, enum power_supply_property *props, int num_props) { @@ -1393,6 +1409,25 @@ static int __init bq27x00_powersupply_init(struct bq27x00_device_info *di) return ret; } + wake_lock_init(&chg_wake_lock, WAKE_LOCK_SUSPEND, "chg_wake_lock"); + + if(di->irq) { + // If using an irq, disable poll interal + poll_interval = 0; + ret = request_irq(di->irq, bq27x00_chg_isr, IRQF_TRIGGER_RISING, + "bq27x00 chg", &di->bat); + if (ret) { + dev_err(di->dev, "failed to request irq: %d\n", di->irq); + return ret; + } + + ret = enable_irq_wake(di->irq); + if (ret) { + dev_err(di->dev, "failed to enable irq: %d, as wake\n", di->irq); + return ret; + } + } + dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION); bq27x00_update(di); @@ -1414,6 +1449,10 @@ static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di) power_supply_unregister(&di->bat); + if(di->irq) { + free_irq(di->irq, di); + } + mutex_destroy(&di->lock); } @@ -1685,6 +1724,7 @@ static int __init bq27x00_battery_probe(struct i2c_client *client, di->bus.blk_write = bq27xxx_write_i2c_blk; di->dm_regs = NULL; di->dm_regs_count = 0; + di->irq = client->irq; if (di->chip == BQ27200) regs = bq27200_regs; |