aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/pda_power.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power/pda_power.c')
-rw-r--r--drivers/power/pda_power.c89
1 files changed, 68 insertions, 21 deletions
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
index 69f8aa3a6a4..fd49689738a 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>
@@ -40,7 +41,9 @@ static int polling;
40 41
41#ifdef CONFIG_USB_OTG_UTILS 42#ifdef CONFIG_USB_OTG_UTILS
42static struct otg_transceiver *transceiver; 43static struct otg_transceiver *transceiver;
44static struct notifier_block otg_nb;
43#endif 45#endif
46
44static struct regulator *ac_draw; 47static struct regulator *ac_draw;
45 48
46enum { 49enum {
@@ -222,7 +225,42 @@ static void polling_timer_func(unsigned long unused)
222#ifdef CONFIG_USB_OTG_UTILS 225#ifdef CONFIG_USB_OTG_UTILS
223static int otg_is_usb_online(void) 226static int otg_is_usb_online(void)
224{ 227{
225 return (transceiver->state == OTG_STATE_B_PERIPHERAL); 228 return (transceiver->last_event == USB_EVENT_VBUS ||
229 transceiver->last_event == USB_EVENT_ENUMERATED);
230}
231
232static int otg_is_ac_online(void)
233{
234 return (transceiver->last_event == USB_EVENT_CHARGER);
235}
236
237static int otg_handle_notification(struct notifier_block *nb,
238 unsigned long event, void *unused)
239{
240 switch (event) {
241 case USB_EVENT_CHARGER:
242 ac_status = PDA_PSY_TO_CHANGE;
243 break;
244 case USB_EVENT_VBUS:
245 case USB_EVENT_ENUMERATED:
246 usb_status = PDA_PSY_TO_CHANGE;
247 break;
248 case USB_EVENT_NONE:
249 ac_status = PDA_PSY_TO_CHANGE;
250 usb_status = PDA_PSY_TO_CHANGE;
251 break;
252 default:
253 return NOTIFY_OK;
254 }
255
256 /*
257 * Wait a bit before reading ac/usb line status and setting charger,
258 * because ac/usb status readings may lag from irq.
259 */
260 mod_timer(&charger_timer,
261 jiffies + msecs_to_jiffies(pdata->wait_for_status));
262
263 return NOTIFY_OK;
226} 264}
227#endif 265#endif
228 266
@@ -282,6 +320,16 @@ static int pda_power_probe(struct platform_device *pdev)
282 ret = PTR_ERR(ac_draw); 320 ret = PTR_ERR(ac_draw);
283 } 321 }
284 322
323#ifdef CONFIG_USB_OTG_UTILS
324 transceiver = otg_get_transceiver();
325 if (transceiver && !pdata->is_usb_online) {
326 pdata->is_usb_online = otg_is_usb_online;
327 }
328 if (transceiver && !pdata->is_ac_online) {
329 pdata->is_ac_online = otg_is_ac_online;
330 }
331#endif
332
285 if (pdata->is_ac_online) { 333 if (pdata->is_ac_online) {
286 ret = power_supply_register(&pdev->dev, &pda_psy_ac); 334 ret = power_supply_register(&pdev->dev, &pda_psy_ac);
287 if (ret) { 335 if (ret) {
@@ -303,13 +351,6 @@ static int pda_power_probe(struct platform_device *pdev)
303 } 351 }
304 } 352 }
305 353
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) { 354 if (pdata->is_usb_online) {
314 ret = power_supply_register(&pdev->dev, &pda_psy_usb); 355 ret = power_supply_register(&pdev->dev, &pda_psy_usb);
315 if (ret) { 356 if (ret) {
@@ -331,6 +372,18 @@ static int pda_power_probe(struct platform_device *pdev)
331 } 372 }
332 } 373 }
333 374
375#ifdef CONFIG_USB_OTG_UTILS
376 if (transceiver && pdata->use_otg_notifier) {
377 otg_nb.notifier_call = otg_handle_notification;
378 ret = otg_register_notifier(transceiver, &otg_nb);
379 if (ret) {
380 dev_err(dev, "failure to register otg notifier\n");
381 goto otg_reg_notifier_failed;
382 }
383 polling = 0;
384 }
385#endif
386
334 if (polling) { 387 if (polling) {
335 dev_dbg(dev, "will poll for status\n"); 388 dev_dbg(dev, "will poll for status\n");
336 setup_timer(&polling_timer, polling_timer_func, 0); 389 setup_timer(&polling_timer, polling_timer_func, 0);
@@ -343,6 +396,11 @@ static int pda_power_probe(struct platform_device *pdev)
343 396
344 return 0; 397 return 0;
345 398
399#ifdef CONFIG_USB_OTG_UTILS
400otg_reg_notifier_failed:
401 if (pdata->is_usb_online && usb_irq)
402 free_irq(usb_irq->start, &pda_psy_usb);
403#endif
346usb_irq_failed: 404usb_irq_failed:
347 if (pdata->is_usb_online) 405 if (pdata->is_usb_online)
348 power_supply_unregister(&pda_psy_usb); 406 power_supply_unregister(&pda_psy_usb);
@@ -440,8 +498,6 @@ static int pda_power_resume(struct platform_device *pdev)
440#define pda_power_resume NULL 498#define pda_power_resume NULL
441#endif /* CONFIG_PM */ 499#endif /* CONFIG_PM */
442 500
443MODULE_ALIAS("platform:pda-power");
444
445static struct platform_driver pda_power_pdrv = { 501static struct platform_driver pda_power_pdrv = {
446 .driver = { 502 .driver = {
447 .name = "pda-power", 503 .name = "pda-power",
@@ -452,17 +508,8 @@ static struct platform_driver pda_power_pdrv = {
452 .resume = pda_power_resume, 508 .resume = pda_power_resume,
453}; 509};
454 510
455static int __init pda_power_init(void) 511module_platform_driver(pda_power_pdrv);
456{
457 return platform_driver_register(&pda_power_pdrv);
458}
459 512
460static void __exit pda_power_exit(void)
461{
462 platform_driver_unregister(&pda_power_pdrv);
463}
464
465module_init(pda_power_init);
466module_exit(pda_power_exit);
467MODULE_LICENSE("GPL"); 513MODULE_LICENSE("GPL");
468MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>"); 514MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
515MODULE_ALIAS("platform:pda-power");