diff options
Diffstat (limited to 'recipes/kexecboot/linux-kexecboot-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch')
-rw-r--r-- | recipes/kexecboot/linux-kexecboot-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/recipes/kexecboot/linux-kexecboot-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch b/recipes/kexecboot/linux-kexecboot-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch new file mode 100644 index 0000000000..6269016223 --- /dev/null +++ b/recipes/kexecboot/linux-kexecboot-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch @@ -0,0 +1,133 @@ +From a637c5056ef52fbb7c41eb7537a9ec3d150231ad Mon Sep 17 00:00:00 2001 +From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +Date: Thu, 2 Apr 2009 10:16:11 -0700 +Subject: [PATCH] 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-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> +--- + drivers/usb/musb/musb_core.c | 27 ++++++++++++++++----------- + drivers/usb/musb/musb_gadget.c | 2 +- + 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 05c5dd3..9dc995a 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, + if (devctl & MUSB_DEVCTL_LSDEV) + musb->port1_status |= USB_PORT_STAT_LOW_SPEED; + +- if (hcd->status_urb) +- usb_hcd_poll_rh_status(hcd); +- else +- usb_hcd_resume_root_hub(hcd); +- +- MUSB_HST_MODE(musb); +- + /* indicate new connection to OTG machine */ + switch (musb->xceiv->state) { + case OTG_STATE_B_PERIPHERAL: + if (int_usb & MUSB_INTR_SUSPEND) { + DBG(1, "HNP: SUSPEND+CONNECT, now b_host\n"); +- musb->xceiv->state = OTG_STATE_B_HOST; +- hcd->self.is_b_host = 1; + int_usb &= ~MUSB_INTR_SUSPEND; ++ goto b_host; + } else + DBG(1, "CONNECT as b_peripheral???\n"); + break; + case OTG_STATE_B_WAIT_ACON: +- DBG(1, "HNP: Waiting to switch to b_host state\n"); ++ DBG(1, "HNP: CONNECT, now b_host\n"); ++b_host: + musb->xceiv->state = OTG_STATE_B_HOST; + hcd->self.is_b_host = 1; ++ musb->ignore_disconnect = 0; ++ del_timer(&musb->otg_timer); + break; + default: + if ((devctl & MUSB_DEVCTL_VBUS) +@@ -618,6 +613,14 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + } + break; + } ++ ++ /* poke the root hub */ ++ MUSB_HST_MODE(musb); ++ if (hcd->status_urb) ++ usb_hcd_poll_rh_status(hcd); ++ else ++ usb_hcd_resume_root_hub(hcd); ++ + DBG(1, "CONNECT (%s) devctl %02x\n", + otg_state_string(musb), devctl); + } +@@ -662,7 +665,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, + + msecs_to_jiffies(TA_WAIT_BCON(musb))); + break; + case OTG_STATE_A_PERIPHERAL: +- musb_hnp_stop(musb); ++ musb->ignore_disconnect = 0; ++ del_timer(&musb->otg_timer); ++ musb_g_reset(musb); + break; + case OTG_STATE_B_WAIT_ACON: + 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 2fbfba5..7dd3d59 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) + musb->xceiv->state = OTG_STATE_A_IDLE; + break; + case OTG_STATE_A_PERIPHERAL: +- musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; ++ musb->xceiv->state = OTG_STATE_A_WAIT_BCON; + break; + case OTG_STATE_B_WAIT_ACON: + case OTG_STATE_B_HOST: +diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c +index 7e7900f..14f7cf3 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) + musb->is_active = 0; + + switch (musb->xceiv->state) { +- case OTG_STATE_A_HOST: + case OTG_STATE_A_SUSPEND: ++#ifdef CONFIG_USB_MUSB_OTG ++ if (is_otg_enabled(musb) ++ && musb->xceiv->host->b_hnp_enable) { ++ musb->xceiv->state = OTG_STATE_A_PERIPHERAL; ++ musb->g.is_a_peripheral = 1; ++ break; ++ } ++#endif ++ /* FALLTHROUGH */ ++ case OTG_STATE_A_HOST: + musb->xceiv->state = OTG_STATE_A_WAIT_BCON; + musb->is_active = 0; + break; +-- +1.6.0.4 + |