aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2009-04-02 13:16:11 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:41 -0400
commit1de00dae8036dfee44ebea2c38f942fb6072e0b7 (patch)
tree35d384cb2fe51ac384da554042450e7d24d190b0
parentf7f9d63eac12b345d6243d1d608b7944a05be921 (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>
-rw-r--r--drivers/usb/musb/musb_core.c27
-rw-r--r--drivers/usb/musb/musb_gadget.c2
-rw-r--r--drivers/usb/musb/musb_virthub.c11
3 files changed, 27 insertions, 13 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 8bd6bb1b04ef..93dd23a7eb6c 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");
602b_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 8dfad1189da2..3c4da75fbc7b 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 d7e1bc44f00a..c85a82a41d5c 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;