diff options
| author | Felipe Balbi <felipe.balbi@nokia.com> | 2009-12-17 06:01:37 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-02 17:53:21 -0500 |
| commit | d1b5b5c0a8a8204f0c51d5eb99736ecfb2fd5b4e (patch) | |
| tree | bc6f229bdcdd716d25efc4603d933eacbdd3d1c8 | |
| parent | e9a20171dfa0aa134d2211126d1310f2daea52cf (diff) | |
USB: otg: twl4030: add support for notifier
it's expected that the transceiver driver will
initialize and call the notifier chain when
necessary. Implement that for twl4030-usb driver.
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
| -rw-r--r-- | drivers/usb/otg/twl4030-usb.c | 35 |
1 files changed, 14 insertions, 21 deletions
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 2be9f2fa41f9..34452d95b386 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; |
| @@ -585,8 +576,7 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) | |||
| 585 | #endif | 576 | #endif |
| 586 | 577 | ||
| 587 | status = twl4030_usb_linkstat(twl); | 578 | status = twl4030_usb_linkstat(twl); |
| 588 | if (status != USB_LINK_UNKNOWN) { | 579 | if (status >= 0) { |
| 589 | |||
| 590 | /* FIXME add a set_power() method so that B-devices can | 580 | /* FIXME add a set_power() method so that B-devices can |
| 591 | * configure the charger appropriately. It's not always | 581 | * configure the charger appropriately. It's not always |
| 592 | * correct to consume VBUS power, and how much current to | 582 | * correct to consume VBUS power, and how much current to |
| @@ -598,12 +588,13 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) | |||
| 598 | * USB_LINK_VBUS state. musb_hdrc won't care until it | 588 | * USB_LINK_VBUS state. musb_hdrc won't care until it |
| 599 | * starts to handle softconnect right. | 589 | * starts to handle softconnect right. |
| 600 | */ | 590 | */ |
| 601 | if (status == USB_LINK_NONE) | 591 | if (status == USB_EVENT_NONE) |
| 602 | twl4030_phy_suspend(twl, 0); | 592 | twl4030_phy_suspend(twl, 0); |
| 603 | else | 593 | else |
| 604 | twl4030_phy_resume(twl); | 594 | twl4030_phy_resume(twl); |
| 605 | 595 | ||
| 606 | twl4030charger_usb_en(status == USB_LINK_VBUS); | 596 | blocking_notifier_call_chain(&twl->otg.notifier, status, |
| 597 | twl->otg.gadget); | ||
| 607 | } | 598 | } |
| 608 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); | 599 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); |
| 609 | 600 | ||
| @@ -693,6 +684,8 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) | |||
| 693 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) | 684 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) |
| 694 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | 685 | dev_warn(&pdev->dev, "could not create sysfs file\n"); |
| 695 | 686 | ||
| 687 | BLOCKING_INIT_NOTIFIER_HEAD(&twl->otg.notifier); | ||
| 688 | |||
| 696 | /* Our job is to use irqs and status from the power module | 689 | /* Our job is to use irqs and status from the power module |
| 697 | * to keep the transceiver disabled when nothing's connected. | 690 | * to keep the transceiver disabled when nothing's connected. |
| 698 | * | 691 | * |
