diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-20 10:19:07 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-20 10:19:07 -0800 |
commit | 5a1203914a637b642442a861cf462d16401548e1 (patch) | |
tree | 894ea523ad45686b9103410f7daeb3a8e670553a /drivers/power/ds2782_battery.c | |
parent | c560dc8793ecf4c3bb4ba6e7b8cae8a64486d96b (diff) | |
parent | ac6324e7021dfa917ce4f9a836318c3e46fbb84e (diff) |
Merge tag 'for-v3.9' of git://git.infradead.org/battery-2.6
Pull battery updates from Anton Vorontsov:
"Four new drivers:
- goldfish_battery:
This is Android Emulator battery driver. Originally from Google,
but Intel folks reshaped it for mainline
- pm2301_charger:
A new driver for ST-Ericsson 2301 Power Management chip, uses
AB8500 battery management core
- qnap-poweroff:
The driver adds poweroff functionality for QNAP NAS boxes
- restart-poweroff:
A generic driver that implements 'power off by restarting'. The
actual poweroff functionality is implemented through a bootloader,
so Linux' task is just to restart the box. The driver is useful on
Buffalo Linkstation LS-XHL and LS-CHLv2 boards. Andrew Lunn worked
on submitting the driver (as well as qnap-poweroff above).
Additionally:
- A lot of fixes for ab8500 drivers. This is a part of efforts of
syncing internal ST-Ericsson development tree with the mainline.
Lee Jones @ Linaro worked on compilation and reshaping these
series.
- New health properties for the power supplies: "Watchdog timer
expire" and "Safety timer expire"
- As usual, a bunch of fixes/cleanups here and there"
* tag 'for-v3.9' of git://git.infradead.org/battery-2.6: (81 commits)
bq2415x_charger: Add support for offline and 100mA mode
generic-adc-battery: Fix forever loop in gab_remove()
goldfish_battery: Add missing GENERIC_HARDIRQS dependency
da9030_battery: Include notifier.h
bq27x00_battery: Fix reporting battery temperature
power/reset: Remove newly introduced __dev* annotations
lp8727_charger: Small cleanup in naming
ab8500_btemp: Demote initcall sequence
ds2782_battery: Add power_supply_changed() calls for proper uevent support
power: Add battery driver for goldfish emulator
u8500-charger: Delay for USB enumeration
ab8500-bm: Remove individual [charger|btemp|fg|chargalg] pdata structures
ab8500-charger: Do not touch VBUSOVV bits
ab8500-fg: Use correct battery charge full design
pm2301: LPN mode control support
pm2301: Enable vbat low monitoring
ab8500-bm: Flush all work queues before suspending
ab8500-fg: Go to INIT_RECOVERY when charger removed
ab8500-charger: Add support for autopower on AB8505 and AB9540
abx500-chargalg: Add new sysfs interface to get current charge status
...
Fix up fairly straightforward conflicts in the ab8500 driver. But since
it seems to be ARM-specific, I can't even compile-test the result..
Diffstat (limited to 'drivers/power/ds2782_battery.c')
-rw-r--r-- | drivers/power/ds2782_battery.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index 2fa9b6bf1f3f..e7301b3ed623 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c @@ -7,6 +7,8 @@ * * DS2786 added by Yulia Vilensky <vilensky@compulab.co.il> * + * UEvent sending added by Evgeny Romanov <romanov@neurosoft.ru> + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -19,6 +21,7 @@ #include <linux/errno.h> #include <linux/swab.h> #include <linux/i2c.h> +#include <linux/delay.h> #include <linux/idr.h> #include <linux/power_supply.h> #include <linux/slab.h> @@ -40,6 +43,8 @@ #define DS2786_CURRENT_UNITS 25 +#define DS278x_DELAY 1000 + struct ds278x_info; struct ds278x_battery_ops { @@ -54,8 +59,11 @@ struct ds278x_info { struct i2c_client *client; struct power_supply battery; struct ds278x_battery_ops *ops; + struct delayed_work bat_work; int id; int rsns; + int capacity; + int status; /* State Of Charge */ }; static DEFINE_IDR(battery_id); @@ -220,6 +228,8 @@ static int ds278x_get_status(struct ds278x_info *info, int *status) if (err) return err; + info->capacity = capacity; + if (capacity == 100) *status = POWER_SUPPLY_STATUS_FULL; else if (current_uA == 0) @@ -267,6 +277,27 @@ static int ds278x_battery_get_property(struct power_supply *psy, return ret; } +static void ds278x_bat_update(struct ds278x_info *info) +{ + int old_status = info->status; + int old_capacity = info->capacity; + + ds278x_get_status(info, &info->status); + + if ((old_status != info->status) || (old_capacity != info->capacity)) + power_supply_changed(&info->battery); +} + +static void ds278x_bat_work(struct work_struct *work) +{ + struct ds278x_info *info; + + info = container_of(work, struct ds278x_info, bat_work.work); + ds278x_bat_update(info); + + schedule_delayed_work(&info->bat_work, DS278x_DELAY); +} + static enum power_supply_property ds278x_battery_props[] = { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_CAPACITY, @@ -295,10 +326,39 @@ static int ds278x_battery_remove(struct i2c_client *client) idr_remove(&battery_id, info->id); mutex_unlock(&battery_lock); + cancel_delayed_work(&info->bat_work); + kfree(info); return 0; } +#ifdef CONFIG_PM + +static int ds278x_suspend(struct i2c_client *client, + pm_message_t state) +{ + struct ds278x_info *info = i2c_get_clientdata(client); + + cancel_delayed_work(&info->bat_work); + return 0; +} + +static int ds278x_resume(struct i2c_client *client) +{ + struct ds278x_info *info = i2c_get_clientdata(client); + + schedule_delayed_work(&info->bat_work, DS278x_DELAY); + return 0; +} + +#else + +#define ds278x_suspend NULL +#define ds278x_resume NULL + +#endif /* CONFIG_PM */ + + enum ds278x_num_id { DS2782 = 0, DS2786, @@ -368,10 +428,17 @@ static int ds278x_battery_probe(struct i2c_client *client, info->ops = &ds278x_ops[id->driver_data]; ds278x_power_supply_init(&info->battery); + info->capacity = 100; + info->status = POWER_SUPPLY_STATUS_FULL; + + INIT_DELAYED_WORK(&info->bat_work, ds278x_bat_work); + ret = power_supply_register(&client->dev, &info->battery); if (ret) { dev_err(&client->dev, "failed to register battery\n"); goto fail_register; + } else { + schedule_delayed_work(&info->bat_work, DS278x_DELAY); } return 0; @@ -401,6 +468,8 @@ static struct i2c_driver ds278x_battery_driver = { }, .probe = ds278x_battery_probe, .remove = ds278x_battery_remove, + .suspend = ds278x_suspend, + .resume = ds278x_resume, .id_table = ds278x_id, }; module_i2c_driver(ds278x_battery_driver); |