aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/pda_power.c')
-rw-r--r--drivers/power/pda_power.c71
1 files changed, 59 insertions, 12 deletions
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
index 69f8aa3a6a4..81b720107c3 100644
--- a/drivers/power/pda_power.c
+++ b/drivers/power/pda_power.c
@@ -14,6 +14,7 @@
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/err.h> 15#include <linux/err.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/notifier.h>
17#include <linux/power_supply.h> 18#include <linux/power_supply.h>
18#include <linux/pda_power.h> 19#include <linux/pda_power.h>
19#include <linux/regulator/consumer.h> 20#include <linux/regulator/consumer.h>
@@ -38,9 +39,8 @@ static struct timer_list supply_timer;
38static struct timer_list polling_timer; 39static struct timer_list polling_timer;
39static int polling; 40static int polling;
40 41
41#ifdef CONFIG_USB_OTG_UTILS
42static struct otg_transceiver *transceiver; 42static struct otg_transceiver *transceiver;
43#endif 43static struct notifier_block otg_nb;
44static struct regulator *ac_draw; 44static struct regulator *ac_draw;
45 45
46enum { 46enum {
@@ -222,7 +222,42 @@ static void polling_timer_func(unsigned long unused)
222#ifdef CONFIG_USB_OTG_UTILS 222#ifdef CONFIG_USB_OTG_UTILS
223static int otg_is_usb_online(void) 223static int otg_is_usb_online(void)
224{ 224{
225 return (transceiver->state == OTG_STATE_B_PERIPHERAL); 225 return (transceiver->last_event == USB_EVENT_VBUS ||
226 transceiver->last_event == USB_EVENT_ENUMERATED);
227}
228
229static int otg_is_ac_online(void)
230{
231 return (transceiver->last_event == USB_EVENT_CHARGER);
232}
233
234static int otg_handle_notification(struct notifier_block *nb,
235 unsigned long event, void *unused)
236{
237 switch (event) {
238 case USB_EVENT_CHARGER:
239 ac_status = PDA_PSY_TO_CHANGE;
240 break;
241 case USB_EVENT_VBUS:
242 case USB_EVENT_ENUMERATED:
243 usb_status = PDA_PSY_TO_CHANGE;
244 break;
245 case USB_EVENT_NONE:
246 ac_status = PDA_PSY_TO_CHANGE;
247 usb_status = PDA_PSY_TO_CHANGE;
248 break;
249 default:
250 return NOTIFY_OK;
251 }
252
253 /*
254 * Wait a bit before reading ac/usb line status and setting charger,
255 * because ac/usb status readings may lag from irq.
256 */
257 mod_timer(&charger_timer,
258 jiffies + msecs_to_jiffies(pdata->wait_for_status));
259
260 return NOTIFY_OK;
226} 261}
227#endif 262#endif
228 263
@@ -282,6 +317,14 @@ static int pda_power_probe(struct platform_device *pdev)
282 ret = PTR_ERR(ac_draw); 317 ret = PTR_ERR(ac_draw);
283 } 318 }
284 319
320 transceiver = otg_get_transceiver();
321 if (transceiver && !pdata->is_usb_online) {
322 pdata->is_usb_online = otg_is_usb_online;
323 }
324 if (transceiver && !pdata->is_ac_online) {
325 pdata->is_ac_online = otg_is_ac_online;
326 }
327
285 if (pdata->is_ac_online) { 328 if (pdata->is_ac_online) {
286 ret = power_supply_register(&pdev->dev, &pda_psy_ac); 329 ret = power_supply_register(&pdev->dev, &pda_psy_ac);
287 if (ret) { 330 if (ret) {
@@ -303,13 +346,6 @@ static int pda_power_probe(struct platform_device *pdev)
303 } 346 }
304 } 347 }
305 348
306#ifdef CONFIG_USB_OTG_UTILS
307 transceiver = otg_get_transceiver();
308 if (transceiver && !pdata->is_usb_online) {
309 pdata->is_usb_online = otg_is_usb_online;
310 }
311#endif
312
313 if (pdata->is_usb_online) { 349 if (pdata->is_usb_online) {
314 ret = power_supply_register(&pdev->dev, &pda_psy_usb); 350 ret = power_supply_register(&pdev->dev, &pda_psy_usb);
315 if (ret) { 351 if (ret) {
@@ -331,6 +367,16 @@ static int pda_power_probe(struct platform_device *pdev)
331 } 367 }
332 } 368 }
333 369
370 if (transceiver && pdata->use_otg_notifier) {
371 otg_nb.notifier_call = otg_handle_notification;
372 ret = otg_register_notifier(transceiver, &otg_nb);
373 if (ret) {
374 dev_err(dev, "failure to register otg notifier\n");
375 goto otg_reg_notifier_failed;
376 }
377 polling = 0;
378 }
379
334 if (polling) { 380 if (polling) {
335 dev_dbg(dev, "will poll for status\n"); 381 dev_dbg(dev, "will poll for status\n");
336 setup_timer(&polling_timer, polling_timer_func, 0); 382 setup_timer(&polling_timer, polling_timer_func, 0);
@@ -343,16 +389,17 @@ static int pda_power_probe(struct platform_device *pdev)
343 389
344 return 0; 390 return 0;
345 391
392otg_reg_notifier_failed:
393 if (pdata->is_usb_online && usb_irq)
394 free_irq(usb_irq->start, &pda_psy_usb);
346usb_irq_failed: 395usb_irq_failed:
347 if (pdata->is_usb_online) 396 if (pdata->is_usb_online)
348 power_supply_unregister(&pda_psy_usb); 397 power_supply_unregister(&pda_psy_usb);
349usb_supply_failed: 398usb_supply_failed:
350 if (pdata->is_ac_online && ac_irq) 399 if (pdata->is_ac_online && ac_irq)
351 free_irq(ac_irq->start, &pda_psy_ac); 400 free_irq(ac_irq->start, &pda_psy_ac);
352#ifdef CONFIG_USB_OTG_UTILS
353 if (transceiver) 401 if (transceiver)
354 otg_put_transceiver(transceiver); 402 otg_put_transceiver(transceiver);
355#endif
356ac_irq_failed: 403ac_irq_failed:
357 if (pdata->is_ac_online) 404 if (pdata->is_ac_online)
358 power_supply_unregister(&pda_psy_ac); 405 power_supply_unregister(&pda_psy_ac);