aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/phy/phy-twl6030-usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/phy/phy-twl6030-usb.c')
-rw-r--r--drivers/usb/phy/phy-twl6030-usb.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
index 24e2b3cf1867..a72e8d670adc 100644
--- a/drivers/usb/phy/phy-twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -97,6 +97,9 @@ struct twl6030_usb {
97 97
98 struct regulator *usb3v3; 98 struct regulator *usb3v3;
99 99
100 /* used to check initial cable status after probe */
101 struct delayed_work get_status_work;
102
100 /* used to set vbus, in atomic path */ 103 /* used to set vbus, in atomic path */
101 struct work_struct set_vbus_work; 104 struct work_struct set_vbus_work;
102 105
@@ -227,12 +230,16 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
227 twl->asleep = 1; 230 twl->asleep = 1;
228 status = MUSB_VBUS_VALID; 231 status = MUSB_VBUS_VALID;
229 twl->linkstat = status; 232 twl->linkstat = status;
230 musb_mailbox(status); 233 ret = musb_mailbox(status);
234 if (ret)
235 twl->linkstat = MUSB_UNKNOWN;
231 } else { 236 } else {
232 if (twl->linkstat != MUSB_UNKNOWN) { 237 if (twl->linkstat != MUSB_UNKNOWN) {
233 status = MUSB_VBUS_OFF; 238 status = MUSB_VBUS_OFF;
234 twl->linkstat = status; 239 twl->linkstat = status;
235 musb_mailbox(status); 240 ret = musb_mailbox(status);
241 if (ret)
242 twl->linkstat = MUSB_UNKNOWN;
236 if (twl->asleep) { 243 if (twl->asleep) {
237 regulator_disable(twl->usb3v3); 244 regulator_disable(twl->usb3v3);
238 twl->asleep = 0; 245 twl->asleep = 0;
@@ -264,7 +271,9 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
264 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); 271 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
265 status = MUSB_ID_GROUND; 272 status = MUSB_ID_GROUND;
266 twl->linkstat = status; 273 twl->linkstat = status;
267 musb_mailbox(status); 274 ret = musb_mailbox(status);
275 if (ret)
276 twl->linkstat = MUSB_UNKNOWN;
268 } else { 277 } else {
269 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR); 278 twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
270 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); 279 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
@@ -274,6 +283,15 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
274 return IRQ_HANDLED; 283 return IRQ_HANDLED;
275} 284}
276 285
286static void twl6030_status_work(struct work_struct *work)
287{
288 struct twl6030_usb *twl = container_of(work, struct twl6030_usb,
289 get_status_work.work);
290
291 twl6030_usb_irq(twl->irq2, twl);
292 twl6030_usbotg_irq(twl->irq1, twl);
293}
294
277static int twl6030_enable_irq(struct twl6030_usb *twl) 295static int twl6030_enable_irq(struct twl6030_usb *twl)
278{ 296{
279 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); 297 twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
@@ -284,8 +302,6 @@ static int twl6030_enable_irq(struct twl6030_usb *twl)
284 REG_INT_MSK_LINE_C); 302 REG_INT_MSK_LINE_C);
285 twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK, 303 twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
286 REG_INT_MSK_STS_C); 304 REG_INT_MSK_STS_C);
287 twl6030_usb_irq(twl->irq2, twl);
288 twl6030_usbotg_irq(twl->irq1, twl);
289 305
290 return 0; 306 return 0;
291} 307}
@@ -371,6 +387,7 @@ static int twl6030_usb_probe(struct platform_device *pdev)
371 dev_warn(&pdev->dev, "could not create sysfs file\n"); 387 dev_warn(&pdev->dev, "could not create sysfs file\n");
372 388
373 INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); 389 INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
390 INIT_DELAYED_WORK(&twl->get_status_work, twl6030_status_work);
374 391
375 status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq, 392 status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
376 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, 393 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
@@ -395,6 +412,7 @@ static int twl6030_usb_probe(struct platform_device *pdev)
395 412
396 twl->asleep = 0; 413 twl->asleep = 0;
397 twl6030_enable_irq(twl); 414 twl6030_enable_irq(twl);
415 schedule_delayed_work(&twl->get_status_work, HZ);
398 dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); 416 dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
399 417
400 return 0; 418 return 0;
@@ -404,6 +422,7 @@ static int twl6030_usb_remove(struct platform_device *pdev)
404{ 422{
405 struct twl6030_usb *twl = platform_get_drvdata(pdev); 423 struct twl6030_usb *twl = platform_get_drvdata(pdev);
406 424
425 cancel_delayed_work(&twl->get_status_work);
407 twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, 426 twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
408 REG_INT_MSK_LINE_C); 427 REG_INT_MSK_LINE_C);
409 twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, 428 twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,