diff options
Diffstat (limited to 'drivers/power/wm97xx_battery.c')
-rw-r--r-- | drivers/power/wm97xx_battery.c | 79 |
1 files changed, 61 insertions, 18 deletions
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c index b787335a841..f2bfd296dba 100644 --- a/drivers/power/wm97xx_battery.c +++ b/drivers/power/wm97xx_battery.c @@ -22,17 +22,20 @@ #include <linux/spinlock.h> #include <linux/interrupt.h> #include <linux/gpio.h> -#include <linux/wm97xx_batt.h> +#include <linux/irq.h> static DEFINE_MUTEX(bat_lock); static struct work_struct bat_work; struct mutex work_lock; static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN; -static struct wm97xx_batt_info *pdata; +static struct wm97xx_batt_info *gpdata; static enum power_supply_property *prop; static unsigned long wm97xx_read_bat(struct power_supply *bat_ps) { + struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data; + struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata; + return wm97xx_read_aux_adc(dev_get_drvdata(bat_ps->dev->parent), pdata->batt_aux) * pdata->batt_mult / pdata->batt_div; @@ -40,6 +43,9 @@ static unsigned long wm97xx_read_bat(struct power_supply *bat_ps) static unsigned long wm97xx_read_temp(struct power_supply *bat_ps) { + struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data; + struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata; + return wm97xx_read_aux_adc(dev_get_drvdata(bat_ps->dev->parent), pdata->temp_aux) * pdata->temp_mult / pdata->temp_div; @@ -49,6 +55,9 @@ static int wm97xx_bat_get_property(struct power_supply *bat_ps, enum power_supply_property psp, union power_supply_propval *val) { + struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data; + struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata; + switch (psp) { case POWER_SUPPLY_PROP_STATUS: val->intval = bat_status; @@ -97,6 +106,8 @@ static void wm97xx_bat_external_power_changed(struct power_supply *bat_ps) static void wm97xx_bat_update(struct power_supply *bat_ps) { int old_status = bat_status; + struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data; + struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata; mutex_lock(&work_lock); @@ -127,21 +138,29 @@ static void wm97xx_bat_work(struct work_struct *work) wm97xx_bat_update(&bat_ps); } +static irqreturn_t wm97xx_chrg_irq(int irq, void *data) +{ + schedule_work(&bat_work); + return IRQ_HANDLED; +} + #ifdef CONFIG_PM -static int wm97xx_bat_suspend(struct platform_device *dev, pm_message_t state) +static int wm97xx_bat_suspend(struct device *dev) { flush_scheduled_work(); return 0; } -static int wm97xx_bat_resume(struct platform_device *dev) +static int wm97xx_bat_resume(struct device *dev) { schedule_work(&bat_work); return 0; } -#else -#define wm97xx_bat_suspend NULL -#define wm97xx_bat_resume NULL + +static struct dev_pm_ops wm97xx_bat_pm_ops = { + .suspend = wm97xx_bat_suspend, + .resume = wm97xx_bat_resume, +}; #endif static int __devinit wm97xx_bat_probe(struct platform_device *dev) @@ -149,6 +168,15 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev) int ret = 0; int props = 1; /* POWER_SUPPLY_PROP_PRESENT */ int i = 0; + struct wm97xx_pdata *wmdata = dev->dev.platform_data; + struct wm97xx_batt_pdata *pdata; + + if (gpdata) { + dev_err(&dev->dev, "Do not pass platform_data through " + "wm97xx_bat_set_pdata!\n"); + return -EINVAL; + } else + pdata = wmdata->batt_pdata; if (dev->id != -1) return -EINVAL; @@ -156,17 +184,22 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev) mutex_init(&work_lock); if (!pdata) { - dev_err(&dev->dev, "Please use wm97xx_bat_set_pdata\n"); + dev_err(&dev->dev, "No platform_data supplied\n"); return -EINVAL; } - if (pdata->charge_gpio >= 0 && gpio_is_valid(pdata->charge_gpio)) { + if (gpio_is_valid(pdata->charge_gpio)) { ret = gpio_request(pdata->charge_gpio, "BATT CHRG"); if (ret) goto err; ret = gpio_direction_input(pdata->charge_gpio); if (ret) goto err2; + ret = request_irq(gpio_to_irq(pdata->charge_gpio), + wm97xx_chrg_irq, IRQF_DISABLED, + "AC Detect", 0); + if (ret) + goto err2; props++; /* POWER_SUPPLY_PROP_STATUS */ } @@ -183,7 +216,7 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev) prop = kzalloc(props * sizeof(*prop), GFP_KERNEL); if (!prop) - goto err2; + goto err3; prop[i++] = POWER_SUPPLY_PROP_PRESENT; if (pdata->charge_gpio >= 0) @@ -216,21 +249,30 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev) if (!ret) schedule_work(&bat_work); else - goto err3; + goto err4; return 0; -err3: +err4: kfree(prop); +err3: + if (gpio_is_valid(pdata->charge_gpio)) + free_irq(gpio_to_irq(pdata->charge_gpio), dev); err2: - gpio_free(pdata->charge_gpio); + if (gpio_is_valid(pdata->charge_gpio)) + gpio_free(pdata->charge_gpio); err: return ret; } static int __devexit wm97xx_bat_remove(struct platform_device *dev) { - if (pdata && pdata->charge_gpio && pdata->charge_gpio >= 0) + struct wm97xx_pdata *wmdata = dev->dev.platform_data; + struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata; + + if (pdata && gpio_is_valid(pdata->charge_gpio)) { + free_irq(gpio_to_irq(pdata->charge_gpio), dev); gpio_free(pdata->charge_gpio); + } flush_scheduled_work(); power_supply_unregister(&bat_ps); kfree(prop); @@ -241,11 +283,12 @@ static struct platform_driver wm97xx_bat_driver = { .driver = { .name = "wm97xx-battery", .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &wm97xx_bat_pm_ops, +#endif }, .probe = wm97xx_bat_probe, .remove = __devexit_p(wm97xx_bat_remove), - .suspend = wm97xx_bat_suspend, - .resume = wm97xx_bat_resume, }; static int __init wm97xx_bat_init(void) @@ -258,9 +301,9 @@ static void __exit wm97xx_bat_exit(void) platform_driver_unregister(&wm97xx_bat_driver); } -void __init wm97xx_bat_set_pdata(struct wm97xx_batt_info *data) +void wm97xx_bat_set_pdata(struct wm97xx_batt_info *data) { - pdata = data; + gpdata = data; } EXPORT_SYMBOL_GPL(wm97xx_bat_set_pdata); |