diff options
Diffstat (limited to 'drivers/usb/otg/twl4030-usb.c')
-rw-r--r-- | drivers/usb/otg/twl4030-usb.c | 45 |
1 files changed, 15 insertions, 30 deletions
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 2be9f2fa41f9..3e4e9f434d78 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #include <linux/i2c/twl.h> | 36 | #include <linux/i2c/twl.h> |
37 | #include <linux/regulator/consumer.h> | 37 | #include <linux/regulator/consumer.h> |
38 | #include <linux/err.h> | 38 | #include <linux/err.h> |
39 | 39 | #include <linux/notifier.h> | |
40 | 40 | ||
41 | /* Register defines */ | 41 | /* Register defines */ |
42 | 42 | ||
@@ -236,15 +236,6 @@ | |||
236 | #define PMBR1 0x0D | 236 | #define PMBR1 0x0D |
237 | #define GPIO_USB_4PIN_ULPI_2430C (3 << 0) | 237 | #define GPIO_USB_4PIN_ULPI_2430C (3 << 0) |
238 | 238 | ||
239 | |||
240 | |||
241 | enum linkstat { | ||
242 | USB_LINK_UNKNOWN = 0, | ||
243 | USB_LINK_NONE, | ||
244 | USB_LINK_VBUS, | ||
245 | USB_LINK_ID, | ||
246 | }; | ||
247 | |||
248 | struct twl4030_usb { | 239 | struct twl4030_usb { |
249 | struct otg_transceiver otg; | 240 | struct otg_transceiver otg; |
250 | struct device *dev; | 241 | struct device *dev; |
@@ -347,10 +338,10 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits) | |||
347 | 338 | ||
348 | /*-------------------------------------------------------------------------*/ | 339 | /*-------------------------------------------------------------------------*/ |
349 | 340 | ||
350 | static enum linkstat twl4030_usb_linkstat(struct twl4030_usb *twl) | 341 | static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl) |
351 | { | 342 | { |
352 | int status; | 343 | int status; |
353 | int linkstat = USB_LINK_UNKNOWN; | 344 | int linkstat = USB_EVENT_NONE; |
354 | 345 | ||
355 | /* | 346 | /* |
356 | * For ID/VBUS sensing, see manual section 15.4.8 ... | 347 | * For ID/VBUS sensing, see manual section 15.4.8 ... |
@@ -368,11 +359,11 @@ static enum linkstat twl4030_usb_linkstat(struct twl4030_usb *twl) | |||
368 | dev_err(twl->dev, "USB link status err %d\n", status); | 359 | dev_err(twl->dev, "USB link status err %d\n", status); |
369 | else if (status & (BIT(7) | BIT(2))) { | 360 | else if (status & (BIT(7) | BIT(2))) { |
370 | if (status & BIT(2)) | 361 | if (status & BIT(2)) |
371 | linkstat = USB_LINK_ID; | 362 | linkstat = USB_EVENT_ID; |
372 | else | 363 | else |
373 | linkstat = USB_LINK_VBUS; | 364 | linkstat = USB_EVENT_VBUS; |
374 | } else | 365 | } else |
375 | linkstat = USB_LINK_NONE; | 366 | linkstat = USB_EVENT_NONE; |
376 | 367 | ||
377 | dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", | 368 | dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", |
378 | status, status, linkstat); | 369 | status, status, linkstat); |
@@ -383,7 +374,7 @@ static enum linkstat twl4030_usb_linkstat(struct twl4030_usb *twl) | |||
383 | 374 | ||
384 | spin_lock_irq(&twl->lock); | 375 | spin_lock_irq(&twl->lock); |
385 | twl->linkstat = linkstat; | 376 | twl->linkstat = linkstat; |
386 | if (linkstat == USB_LINK_ID) { | 377 | if (linkstat == USB_EVENT_ID) { |
387 | twl->otg.default_a = true; | 378 | twl->otg.default_a = true; |
388 | twl->otg.state = OTG_STATE_A_IDLE; | 379 | twl->otg.state = OTG_STATE_A_IDLE; |
389 | } else { | 380 | } else { |
@@ -564,7 +555,7 @@ static ssize_t twl4030_usb_vbus_show(struct device *dev, | |||
564 | 555 | ||
565 | spin_lock_irqsave(&twl->lock, flags); | 556 | spin_lock_irqsave(&twl->lock, flags); |
566 | ret = sprintf(buf, "%s\n", | 557 | ret = sprintf(buf, "%s\n", |
567 | (twl->linkstat == USB_LINK_VBUS) ? "on" : "off"); | 558 | (twl->linkstat == USB_EVENT_VBUS) ? "on" : "off"); |
568 | spin_unlock_irqrestore(&twl->lock, flags); | 559 | spin_unlock_irqrestore(&twl->lock, flags); |
569 | 560 | ||
570 | return ret; | 561 | return ret; |
@@ -576,17 +567,8 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) | |||
576 | struct twl4030_usb *twl = _twl; | 567 | struct twl4030_usb *twl = _twl; |
577 | int status; | 568 | int status; |
578 | 569 | ||
579 | #ifdef CONFIG_LOCKDEP | ||
580 | /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which | ||
581 | * we don't want and can't tolerate. Although it might be | ||
582 | * friendlier not to borrow this thread context... | ||
583 | */ | ||
584 | local_irq_enable(); | ||
585 | #endif | ||
586 | |||
587 | status = twl4030_usb_linkstat(twl); | 570 | status = twl4030_usb_linkstat(twl); |
588 | if (status != USB_LINK_UNKNOWN) { | 571 | if (status >= 0) { |
589 | |||
590 | /* FIXME add a set_power() method so that B-devices can | 572 | /* FIXME add a set_power() method so that B-devices can |
591 | * configure the charger appropriately. It's not always | 573 | * configure the charger appropriately. It's not always |
592 | * correct to consume VBUS power, and how much current to | 574 | * correct to consume VBUS power, and how much current to |
@@ -598,12 +580,13 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) | |||
598 | * USB_LINK_VBUS state. musb_hdrc won't care until it | 580 | * USB_LINK_VBUS state. musb_hdrc won't care until it |
599 | * starts to handle softconnect right. | 581 | * starts to handle softconnect right. |
600 | */ | 582 | */ |
601 | if (status == USB_LINK_NONE) | 583 | if (status == USB_EVENT_NONE) |
602 | twl4030_phy_suspend(twl, 0); | 584 | twl4030_phy_suspend(twl, 0); |
603 | else | 585 | else |
604 | twl4030_phy_resume(twl); | 586 | twl4030_phy_resume(twl); |
605 | 587 | ||
606 | twl4030charger_usb_en(status == USB_LINK_VBUS); | 588 | blocking_notifier_call_chain(&twl->otg.notifier, status, |
589 | twl->otg.gadget); | ||
607 | } | 590 | } |
608 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); | 591 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); |
609 | 592 | ||
@@ -693,6 +676,8 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) | |||
693 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) | 676 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) |
694 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | 677 | dev_warn(&pdev->dev, "could not create sysfs file\n"); |
695 | 678 | ||
679 | BLOCKING_INIT_NOTIFIER_HEAD(&twl->otg.notifier); | ||
680 | |||
696 | /* Our job is to use irqs and status from the power module | 681 | /* Our job is to use irqs and status from the power module |
697 | * to keep the transceiver disabled when nothing's connected. | 682 | * to keep the transceiver disabled when nothing's connected. |
698 | * | 683 | * |
@@ -702,7 +687,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) | |||
702 | * need both handles, otherwise just one suffices. | 687 | * need both handles, otherwise just one suffices. |
703 | */ | 688 | */ |
704 | twl->irq_enabled = true; | 689 | twl->irq_enabled = true; |
705 | status = request_irq(twl->irq, twl4030_usb_irq, | 690 | status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq, |
706 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | 691 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, |
707 | "twl4030_usb", twl); | 692 | "twl4030_usb", twl); |
708 | if (status < 0) { | 693 | if (status < 0) { |