aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/otg/twl6030-usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/otg/twl6030-usb.c')
-rw-r--r--drivers/usb/otg/twl6030-usb.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index cfb5aa72b196..b4d2c0972b3d 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -95,11 +95,15 @@ struct twl6030_usb {
95 95
96 struct regulator *usb3v3; 96 struct regulator *usb3v3;
97 97
98 /* used to set vbus, in atomic path */
99 struct work_struct set_vbus_work;
100
98 int irq1; 101 int irq1;
99 int irq2; 102 int irq2;
100 u8 linkstat; 103 u8 linkstat;
101 u8 asleep; 104 u8 asleep;
102 bool irq_enabled; 105 bool irq_enabled;
106 bool vbus_enable;
103 unsigned long features; 107 unsigned long features;
104}; 108};
105 109
@@ -370,20 +374,31 @@ static int twl6030_enable_irq(struct otg_transceiver *x)
370 return 0; 374 return 0;
371} 375}
372 376
373static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled) 377static void otg_set_vbus_work(struct work_struct *data)
374{ 378{
375 struct twl6030_usb *twl = xceiv_to_twl(x); 379 struct twl6030_usb *twl = container_of(data, struct twl6030_usb,
380 set_vbus_work);
376 381
377 /* 382 /*
378 * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1 383 * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1
379 * register. This enables boost mode. 384 * register. This enables boost mode.
380 */ 385 */
381 if (enabled) 386
387 if (twl->vbus_enable)
382 twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40, 388 twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40,
383 CHARGERUSB_CTRL1); 389 CHARGERUSB_CTRL1);
384 else 390 else
385 twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00, 391 twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00,
386 CHARGERUSB_CTRL1); 392 CHARGERUSB_CTRL1);
393}
394
395static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled)
396{
397 struct twl6030_usb *twl = xceiv_to_twl(x);
398
399 twl->vbus_enable = enabled;
400 schedule_work(&twl->set_vbus_work);
401
387 return 0; 402 return 0;
388} 403}
389 404
@@ -444,6 +459,8 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
444 459
445 ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier); 460 ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
446 461
462 INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
463
447 twl->irq_enabled = true; 464 twl->irq_enabled = true;
448 status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq, 465 status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
449 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, 466 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
@@ -494,6 +511,7 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev)
494 regulator_put(twl->usb3v3); 511 regulator_put(twl->usb3v3);
495 pdata->phy_exit(twl->dev); 512 pdata->phy_exit(twl->dev);
496 device_remove_file(twl->dev, &dev_attr_vbus); 513 device_remove_file(twl->dev, &dev_attr_vbus);
514 cancel_work_sync(&twl->set_vbus_work);
497 kfree(twl); 515 kfree(twl);
498 516
499 return 0; 517 return 0;