diff options
Diffstat (limited to 'drivers/usb/otg/twl6030-usb.c')
-rw-r--r-- | drivers/usb/otg/twl6030-usb.c | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index cfb5aa7..9f51eaf 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c @@ -63,9 +63,6 @@ #define USB_OTG_ADP_RISE 0x19 #define USB_OTG_REVISION 0x1A -/* to be moved to LDO */ -#define TWL6030_MISC2 0xE5 -#define TWL6030_CFG_LDO_PD2 0xF5 #define TWL6030_BACKUP_REG 0xFA #define STS_HW_CONDITIONS 0x21 @@ -95,11 +92,15 @@ struct twl6030_usb { struct regulator *usb3v3; + /* used to set vbus, in atomic path */ + struct work_struct set_vbus_work; + int irq1; int irq2; u8 linkstat; u8 asleep; bool irq_enabled; + bool vbus_enable; unsigned long features; }; @@ -215,12 +216,6 @@ static int twl6030_usb_ldo_init(struct twl6030_usb *twl) /* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */ twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG); - /* Program CFG_LDO_PD2 register and set VUSB bit */ - twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_CFG_LDO_PD2); - - /* Program MISC2 register and set bit VUSB_IN_VBAT */ - twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2); - twl->usb3v3 = regulator_get(twl->dev, regulator_name); if (IS_ERR(twl->usb3v3)) return -ENODEV; @@ -370,20 +365,28 @@ static int twl6030_enable_irq(struct otg_transceiver *x) return 0; } -static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled) +static void otg_set_vbus_work(struct work_struct *data) { - struct twl6030_usb *twl = xceiv_to_twl(x); - + struct twl6030_usb *twl = container_of(data, struct twl6030_usb, + set_vbus_work); /* * Start driving VBUS. Set OPA_MODE bit in CHARGERUSB_CTRL1 * register. This enables boost mode. */ - if (enabled) + if (twl->vbus_enable) twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x40, CHARGERUSB_CTRL1); - else + else twl6030_writeb(twl, TWL_MODULE_MAIN_CHARGE , 0x00, CHARGERUSB_CTRL1); +} + +static int twl6030_set_vbus(struct otg_transceiver *x, bool enabled) +{ + struct twl6030_usb *twl = xceiv_to_twl(x); + + twl->vbus_enable = enabled; + schedule_work(&twl->set_vbus_work); return 0; } @@ -444,6 +447,9 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier); + INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); + + twl->vbus_enable = false; twl->irq_enabled = true; status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, @@ -494,6 +500,7 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) regulator_put(twl->usb3v3); pdata->phy_exit(twl->dev); device_remove_file(twl->dev, &dev_attr_vbus); + cancel_work_sync(&twl->set_vbus_work); kfree(twl); return 0; |