diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2009-04-02 13:16:11 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-16 00:44:41 -0400 |
commit | 1de00dae8036dfee44ebea2c38f942fb6072e0b7 (patch) | |
tree | 35d384cb2fe51ac384da554042450e7d24d190b0 /drivers | |
parent | f7f9d63eac12b345d6243d1d608b7944a05be921 (diff) |
musb: make initial HNP roleswitch work (v2)
Minor HNP bugfixes, so the initial role switch works:
- A-Device:
* disconnect-during-suspend enters A_PERIPHERAL state
* kill OTG timer after reset as A_PERIPHERAL ...
* ... and also pass that reset to the gadget
* once HNP succeeds, clear the "ignore_disconnect" flag
* from A_PERIPHERAL, disconnect transitions to A_WAIT_BCON
- B-Device:
* kill OTG timer on entry to B_HOST state (HNP succeeded)
* once HNP succeeds, clear "ignore_disconnect" flag
* kick the root hub only _after_ the state is adjusted
Other state transitions are left alone. Notably, exit paths from
the "roles have switched" state ... A_PERIPHERAL handling of that
stays seriously broken.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/musb/musb_core.c | 27 | ||||
-rw-r--r-- | drivers/usb/musb/musb_gadget.c | 2 | ||||
-rw-r--r-- | drivers/usb/musb/musb_virthub.c | 11 |
3 files changed, 27 insertions, 13 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 8bd6bb1b04e..93dd23a7eb6 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
@@ -587,28 +587,23 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | |||
587 | if (devctl & MUSB_DEVCTL_LSDEV) | 587 | if (devctl & MUSB_DEVCTL_LSDEV) |
588 | musb->port1_status |= USB_PORT_STAT_LOW_SPEED; | 588 | musb->port1_status |= USB_PORT_STAT_LOW_SPEED; |
589 | 589 | ||
590 | if (hcd->status_urb) | ||
591 | usb_hcd_poll_rh_status(hcd); | ||
592 | else | ||
593 | usb_hcd_resume_root_hub(hcd); | ||
594 | |||
595 | MUSB_HST_MODE(musb); | ||
596 | |||
597 | /* indicate new connection to OTG machine */ | 590 | /* indicate new connection to OTG machine */ |
598 | switch (musb->xceiv->state) { | 591 | switch (musb->xceiv->state) { |
599 | case OTG_STATE_B_PERIPHERAL: | 592 | case OTG_STATE_B_PERIPHERAL: |
600 | if (int_usb & MUSB_INTR_SUSPEND) { | 593 | if (int_usb & MUSB_INTR_SUSPEND) { |
601 | DBG(1, "HNP: SUSPEND+CONNECT, now b_host\n"); | 594 | DBG(1, "HNP: SUSPEND+CONNECT, now b_host\n"); |
602 | musb->xceiv->state = OTG_STATE_B_HOST; | ||
603 | hcd->self.is_b_host = 1; | ||
604 | int_usb &= ~MUSB_INTR_SUSPEND; | 595 | int_usb &= ~MUSB_INTR_SUSPEND; |
596 | goto b_host; | ||
605 | } else | 597 | } else |
606 | DBG(1, "CONNECT as b_peripheral???\n"); | 598 | DBG(1, "CONNECT as b_peripheral???\n"); |
607 | break; | 599 | break; |
608 | case OTG_STATE_B_WAIT_ACON: | 600 | case OTG_STATE_B_WAIT_ACON: |
609 | DBG(1, "HNP: Waiting to switch to b_host state\n"); | 601 | DBG(1, "HNP: CONNECT, now b_host\n"); |
602 | b_host: | ||
610 | musb->xceiv->state = OTG_STATE_B_HOST; | 603 | musb->xceiv->state = OTG_STATE_B_HOST; |
611 | hcd->self.is_b_host = 1; | 604 | hcd->self.is_b_host = 1; |
605 | musb->ignore_disconnect = 0; | ||
606 | del_timer(&musb->otg_timer); | ||
612 | break; | 607 | break; |
613 | default: | 608 | default: |
614 | if ((devctl & MUSB_DEVCTL_VBUS) | 609 | if ((devctl & MUSB_DEVCTL_VBUS) |
@@ -618,6 +613,14 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | |||
618 | } | 613 | } |
619 | break; | 614 | break; |
620 | } | 615 | } |
616 | |||
617 | /* poke the root hub */ | ||
618 | MUSB_HST_MODE(musb); | ||
619 | if (hcd->status_urb) | ||
620 | usb_hcd_poll_rh_status(hcd); | ||
621 | else | ||
622 | usb_hcd_resume_root_hub(hcd); | ||
623 | |||
621 | DBG(1, "CONNECT (%s) devctl %02x\n", | 624 | DBG(1, "CONNECT (%s) devctl %02x\n", |
622 | otg_state_string(musb), devctl); | 625 | otg_state_string(musb), devctl); |
623 | } | 626 | } |
@@ -662,7 +665,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | |||
662 | + msecs_to_jiffies(TA_WAIT_BCON(musb))); | 665 | + msecs_to_jiffies(TA_WAIT_BCON(musb))); |
663 | break; | 666 | break; |
664 | case OTG_STATE_A_PERIPHERAL: | 667 | case OTG_STATE_A_PERIPHERAL: |
665 | musb_hnp_stop(musb); | 668 | musb->ignore_disconnect = 0; |
669 | del_timer(&musb->otg_timer); | ||
670 | musb_g_reset(musb); | ||
666 | break; | 671 | break; |
667 | case OTG_STATE_B_WAIT_ACON: | 672 | case OTG_STATE_B_WAIT_ACON: |
668 | DBG(1, "HNP: RESET (%s), to b_peripheral\n", | 673 | DBG(1, "HNP: RESET (%s), to b_peripheral\n", |
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 8dfad1189da..3c4da75fbc7 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c | |||
@@ -1964,7 +1964,7 @@ void musb_g_disconnect(struct musb *musb) | |||
1964 | musb->xceiv->state = OTG_STATE_A_IDLE; | 1964 | musb->xceiv->state = OTG_STATE_A_IDLE; |
1965 | break; | 1965 | break; |
1966 | case OTG_STATE_A_PERIPHERAL: | 1966 | case OTG_STATE_A_PERIPHERAL: |
1967 | musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; | 1967 | musb->xceiv->state = OTG_STATE_A_WAIT_BCON; |
1968 | break; | 1968 | break; |
1969 | case OTG_STATE_B_WAIT_ACON: | 1969 | case OTG_STATE_B_WAIT_ACON: |
1970 | case OTG_STATE_B_HOST: | 1970 | case OTG_STATE_B_HOST: |
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index d7e1bc44f00..c85a82a41d5 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c | |||
@@ -187,8 +187,17 @@ void musb_root_disconnect(struct musb *musb) | |||
187 | musb->is_active = 0; | 187 | musb->is_active = 0; |
188 | 188 | ||
189 | switch (musb->xceiv->state) { | 189 | switch (musb->xceiv->state) { |
190 | case OTG_STATE_A_HOST: | ||
191 | case OTG_STATE_A_SUSPEND: | 190 | case OTG_STATE_A_SUSPEND: |
191 | #ifdef CONFIG_USB_MUSB_OTG | ||
192 | if (is_otg_enabled(musb) | ||
193 | && musb->xceiv->host->b_hnp_enable) { | ||
194 | musb->xceiv->state = OTG_STATE_A_PERIPHERAL; | ||
195 | musb->g.is_a_peripheral = 1; | ||
196 | break; | ||
197 | } | ||
198 | #endif | ||
199 | /* FALLTHROUGH */ | ||
200 | case OTG_STATE_A_HOST: | ||
192 | musb->xceiv->state = OTG_STATE_A_WAIT_BCON; | 201 | musb->xceiv->state = OTG_STATE_A_WAIT_BCON; |
193 | musb->is_active = 0; | 202 | musb->is_active = 0; |
194 | break; | 203 | break; |