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 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 | ||
27 | static DEFINE_MUTEX(bat_lock); | 27 | static DEFINE_MUTEX(bat_lock); |
28 | static struct work_struct bat_work; | 28 | static struct work_struct bat_work; |
29 | struct mutex work_lock; | 29 | struct mutex work_lock; |
30 | static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN; | 30 | static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN; |
31 | static struct wm97xx_batt_info *pdata; | 31 | static struct wm97xx_batt_info *gpdata; |
32 | static enum power_supply_property *prop; | 32 | static enum power_supply_property *prop; |
33 | 33 | ||
34 | static unsigned long wm97xx_read_bat(struct power_supply *bat_ps) | 34 | static 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 | ||
41 | static unsigned long wm97xx_read_temp(struct power_supply *bat_ps) | 44 | static 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) | |||
97 | static void wm97xx_bat_update(struct power_supply *bat_ps) | 106 | static 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 | ||
141 | static 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 |
131 | static int wm97xx_bat_suspend(struct platform_device *dev, pm_message_t state) | 148 | static 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 | ||
137 | static int wm97xx_bat_resume(struct platform_device *dev) | 154 | static 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 | 160 | static 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 | ||
147 | static int __devinit wm97xx_bat_probe(struct platform_device *dev) | 166 | static 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; |
222 | err3: | 255 | err4: |
223 | kfree(prop); | 256 | kfree(prop); |
257 | err3: | ||
258 | if (gpio_is_valid(pdata->charge_gpio)) | ||
259 | free_irq(gpio_to_irq(pdata->charge_gpio), dev); | ||
224 | err2: | 260 | err2: |
225 | gpio_free(pdata->charge_gpio); | 261 | if (gpio_is_valid(pdata->charge_gpio)) |
262 | gpio_free(pdata->charge_gpio); | ||
226 | err: | 263 | err: |
227 | return ret; | 264 | return ret; |
228 | } | 265 | } |
229 | 266 | ||
230 | static int __devexit wm97xx_bat_remove(struct platform_device *dev) | 267 | static 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 | ||
251 | static int __init wm97xx_bat_init(void) | 294 | static 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 | ||
261 | void __init wm97xx_bat_set_pdata(struct wm97xx_batt_info *data) | 304 | void wm97xx_bat_set_pdata(struct wm97xx_batt_info *data) |
262 | { | 305 | { |
263 | pdata = data; | 306 | gpdata = data; |
264 | } | 307 | } |
265 | EXPORT_SYMBOL_GPL(wm97xx_bat_set_pdata); | 308 | EXPORT_SYMBOL_GPL(wm97xx_bat_set_pdata); |
266 | 309 | ||