aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/wm97xx_battery.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/wm97xx_battery.c')
-rw-r--r--drivers/power/wm97xx_battery.c79
1 files changed, 61 insertions, 18 deletions
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c
index b787335a8419..f2bfd296dbae 100644
--- a/drivers/power/wm97xx_battery.c
+++ b/drivers/power/wm97xx_battery.c
@@ -22,17 +22,20 @@
22#include <linux/spinlock.h> 22#include <linux/spinlock.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/gpio.h> 24#include <linux/gpio.h>
25#include <linux/wm97xx_batt.h> 25#include <linux/irq.h>
26 26
27static DEFINE_MUTEX(bat_lock); 27static DEFINE_MUTEX(bat_lock);
28static struct work_struct bat_work; 28static struct work_struct bat_work;
29struct mutex work_lock; 29struct mutex work_lock;
30static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN; 30static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN;
31static struct wm97xx_batt_info *pdata; 31static struct wm97xx_batt_info *gpdata;
32static enum power_supply_property *prop; 32static enum power_supply_property *prop;
33 33
34static unsigned long wm97xx_read_bat(struct power_supply *bat_ps) 34static unsigned long wm97xx_read_bat(struct power_supply *bat_ps)
35{ 35{
36 struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data;
37 struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata;
38
36 return wm97xx_read_aux_adc(dev_get_drvdata(bat_ps->dev->parent), 39 return wm97xx_read_aux_adc(dev_get_drvdata(bat_ps->dev->parent),
37 pdata->batt_aux) * pdata->batt_mult / 40 pdata->batt_aux) * pdata->batt_mult /
38 pdata->batt_div; 41 pdata->batt_div;
@@ -40,6 +43,9 @@ static unsigned long wm97xx_read_bat(struct power_supply *bat_ps)
40 43
41static unsigned long wm97xx_read_temp(struct power_supply *bat_ps) 44static unsigned long wm97xx_read_temp(struct power_supply *bat_ps)
42{ 45{
46 struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data;
47 struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata;
48
43 return wm97xx_read_aux_adc(dev_get_drvdata(bat_ps->dev->parent), 49 return wm97xx_read_aux_adc(dev_get_drvdata(bat_ps->dev->parent),
44 pdata->temp_aux) * pdata->temp_mult / 50 pdata->temp_aux) * pdata->temp_mult /
45 pdata->temp_div; 51 pdata->temp_div;
@@ -49,6 +55,9 @@ static int wm97xx_bat_get_property(struct power_supply *bat_ps,
49 enum power_supply_property psp, 55 enum power_supply_property psp,
50 union power_supply_propval *val) 56 union power_supply_propval *val)
51{ 57{
58 struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data;
59 struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata;
60
52 switch (psp) { 61 switch (psp) {
53 case POWER_SUPPLY_PROP_STATUS: 62 case POWER_SUPPLY_PROP_STATUS:
54 val->intval = bat_status; 63 val->intval = bat_status;
@@ -97,6 +106,8 @@ static void wm97xx_bat_external_power_changed(struct power_supply *bat_ps)
97static void wm97xx_bat_update(struct power_supply *bat_ps) 106static void wm97xx_bat_update(struct power_supply *bat_ps)
98{ 107{
99 int old_status = bat_status; 108 int old_status = bat_status;
109 struct wm97xx_pdata *wmdata = bat_ps->dev->parent->platform_data;
110 struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata;
100 111
101 mutex_lock(&work_lock); 112 mutex_lock(&work_lock);
102 113
@@ -127,21 +138,29 @@ static void wm97xx_bat_work(struct work_struct *work)
127 wm97xx_bat_update(&bat_ps); 138 wm97xx_bat_update(&bat_ps);
128} 139}
129 140
141static irqreturn_t wm97xx_chrg_irq(int irq, void *data)
142{
143 schedule_work(&bat_work);
144 return IRQ_HANDLED;
145}
146
130#ifdef CONFIG_PM 147#ifdef CONFIG_PM
131static int wm97xx_bat_suspend(struct platform_device *dev, pm_message_t state) 148static int wm97xx_bat_suspend(struct device *dev)
132{ 149{
133 flush_scheduled_work(); 150 flush_scheduled_work();
134 return 0; 151 return 0;
135} 152}
136 153
137static int wm97xx_bat_resume(struct platform_device *dev) 154static int wm97xx_bat_resume(struct device *dev)
138{ 155{
139 schedule_work(&bat_work); 156 schedule_work(&bat_work);
140 return 0; 157 return 0;
141} 158}
142#else 159
143#define wm97xx_bat_suspend NULL 160static struct dev_pm_ops wm97xx_bat_pm_ops = {
144#define wm97xx_bat_resume NULL 161 .suspend = wm97xx_bat_suspend,
162 .resume = wm97xx_bat_resume,
163};
145#endif 164#endif
146 165
147static int __devinit wm97xx_bat_probe(struct platform_device *dev) 166static int __devinit wm97xx_bat_probe(struct platform_device *dev)
@@ -149,6 +168,15 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
149 int ret = 0; 168 int ret = 0;
150 int props = 1; /* POWER_SUPPLY_PROP_PRESENT */ 169 int props = 1; /* POWER_SUPPLY_PROP_PRESENT */
151 int i = 0; 170 int i = 0;
171 struct wm97xx_pdata *wmdata = dev->dev.platform_data;
172 struct wm97xx_batt_pdata *pdata;
173
174 if (gpdata) {
175 dev_err(&dev->dev, "Do not pass platform_data through "
176 "wm97xx_bat_set_pdata!\n");
177 return -EINVAL;
178 } else
179 pdata = wmdata->batt_pdata;
152 180
153 if (dev->id != -1) 181 if (dev->id != -1)
154 return -EINVAL; 182 return -EINVAL;
@@ -156,17 +184,22 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
156 mutex_init(&work_lock); 184 mutex_init(&work_lock);
157 185
158 if (!pdata) { 186 if (!pdata) {
159 dev_err(&dev->dev, "Please use wm97xx_bat_set_pdata\n"); 187 dev_err(&dev->dev, "No platform_data supplied\n");
160 return -EINVAL; 188 return -EINVAL;
161 } 189 }
162 190
163 if (pdata->charge_gpio >= 0 && gpio_is_valid(pdata->charge_gpio)) { 191 if (gpio_is_valid(pdata->charge_gpio)) {
164 ret = gpio_request(pdata->charge_gpio, "BATT CHRG"); 192 ret = gpio_request(pdata->charge_gpio, "BATT CHRG");
165 if (ret) 193 if (ret)
166 goto err; 194 goto err;
167 ret = gpio_direction_input(pdata->charge_gpio); 195 ret = gpio_direction_input(pdata->charge_gpio);
168 if (ret) 196 if (ret)
169 goto err2; 197 goto err2;
198 ret = request_irq(gpio_to_irq(pdata->charge_gpio),
199 wm97xx_chrg_irq, IRQF_DISABLED,
200 "AC Detect", 0);
201 if (ret)
202 goto err2;
170 props++; /* POWER_SUPPLY_PROP_STATUS */ 203 props++; /* POWER_SUPPLY_PROP_STATUS */
171 } 204 }
172 205
@@ -183,7 +216,7 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
183 216
184 prop = kzalloc(props * sizeof(*prop), GFP_KERNEL); 217 prop = kzalloc(props * sizeof(*prop), GFP_KERNEL);
185 if (!prop) 218 if (!prop)
186 goto err2; 219 goto err3;
187 220
188 prop[i++] = POWER_SUPPLY_PROP_PRESENT; 221 prop[i++] = POWER_SUPPLY_PROP_PRESENT;
189 if (pdata->charge_gpio >= 0) 222 if (pdata->charge_gpio >= 0)
@@ -216,21 +249,30 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
216 if (!ret) 249 if (!ret)
217 schedule_work(&bat_work); 250 schedule_work(&bat_work);
218 else 251 else
219 goto err3; 252 goto err4;
220 253
221 return 0; 254 return 0;
222err3: 255err4:
223 kfree(prop); 256 kfree(prop);
257err3:
258 if (gpio_is_valid(pdata->charge_gpio))
259 free_irq(gpio_to_irq(pdata->charge_gpio), dev);
224err2: 260err2:
225 gpio_free(pdata->charge_gpio); 261 if (gpio_is_valid(pdata->charge_gpio))
262 gpio_free(pdata->charge_gpio);
226err: 263err:
227 return ret; 264 return ret;
228} 265}
229 266
230static int __devexit wm97xx_bat_remove(struct platform_device *dev) 267static int __devexit wm97xx_bat_remove(struct platform_device *dev)
231{ 268{
232 if (pdata && pdata->charge_gpio && pdata->charge_gpio >= 0) 269 struct wm97xx_pdata *wmdata = dev->dev.platform_data;
270 struct wm97xx_batt_pdata *pdata = wmdata->batt_pdata;
271
272 if (pdata && gpio_is_valid(pdata->charge_gpio)) {
273 free_irq(gpio_to_irq(pdata->charge_gpio), dev);
233 gpio_free(pdata->charge_gpio); 274 gpio_free(pdata->charge_gpio);
275 }
234 flush_scheduled_work(); 276 flush_scheduled_work();
235 power_supply_unregister(&bat_ps); 277 power_supply_unregister(&bat_ps);
236 kfree(prop); 278 kfree(prop);
@@ -241,11 +283,12 @@ static struct platform_driver wm97xx_bat_driver = {
241 .driver = { 283 .driver = {
242 .name = "wm97xx-battery", 284 .name = "wm97xx-battery",
243 .owner = THIS_MODULE, 285 .owner = THIS_MODULE,
286#ifdef CONFIG_PM
287 .pm = &wm97xx_bat_pm_ops,
288#endif
244 }, 289 },
245 .probe = wm97xx_bat_probe, 290 .probe = wm97xx_bat_probe,
246 .remove = __devexit_p(wm97xx_bat_remove), 291 .remove = __devexit_p(wm97xx_bat_remove),
247 .suspend = wm97xx_bat_suspend,
248 .resume = wm97xx_bat_resume,
249}; 292};
250 293
251static int __init wm97xx_bat_init(void) 294static int __init wm97xx_bat_init(void)
@@ -258,9 +301,9 @@ static void __exit wm97xx_bat_exit(void)
258 platform_driver_unregister(&wm97xx_bat_driver); 301 platform_driver_unregister(&wm97xx_bat_driver);
259} 302}
260 303
261void __init wm97xx_bat_set_pdata(struct wm97xx_batt_info *data) 304void wm97xx_bat_set_pdata(struct wm97xx_batt_info *data)
262{ 305{
263 pdata = data; 306 gpdata = data;
264} 307}
265EXPORT_SYMBOL_GPL(wm97xx_bat_set_pdata); 308EXPORT_SYMBOL_GPL(wm97xx_bat_set_pdata);
266 309