On 11.10.2013 10:38, Sebastian Andrzej Siewior wrote:
> I have am335x-evm with one port running in OTG mode. Since commit
> fe4cb09 ("usb: musb: gadget: remove hcd initialization") the loaded
> gadget does non pop up on the host. All I see is
> |usb 4-5: new high-speed USB device number 52 using ehci-pci
> |usb 4-5: device descriptor read/64, error -110
> 
> Since a later commit 2cc65fe ("usb: musb: add musb_host_setup() and
> musb_host_cleanup()) the gadget shows up on the host again but only
> in OTG mode (because we have the host init code running). It does not
> work in device only mode.
> If running in OTG mode and the gadget is removed and added back (rmmod
> followed by modprobe of a gadget) then the same error is pops up on the
> host side.
> 
> This patch ensures that the gadget side also executes musb_start() which
> puts the chip in "connect accept" mode. With this change the device
> works in OTG & device mode and the gadget can be added & removed
> multiple times.
> A device (if musb is in OTG mode acting as a host) is only recognized if
> it is attached during module load (musb_hdrc module). After the device
> unplugged and plugged again the host does not recognize it. We get a
> buch of errors if musb running in OTG mode, attached to a host and no
> gadget is loaded. Bah.
> This is one step forward. Host & device only mode should work. I will
> look at OTG later. I looked at this before commit fe4cb09 and OTG wasn't
> working there perfectly so I am not sure that it is a regression :)
> 
> Cc: Daniel Mack <zon...@gmail.com>
> Cc: Peter Korsgaard <jac...@sunsite.dk>
> Signed-off-by: Sebastian Andrzej Siewior <bige...@linutronix.de>

Looks good to me - successfully tested on my host-only board.

  Tested-by: Daniel Mack <zon...@gmail.com>

I'll rebase my suspend patches on top of them, address the port reset
details and repost.


Thanks,
Daniel


> ---
>  drivers/usb/musb/musb_core.c    | 46 
> +++++++++++++++++++++++++++++++++++++++++
>  drivers/usb/musb/musb_core.h    |  1 +
>  drivers/usb/musb/musb_gadget.c  |  2 ++
>  drivers/usb/musb/musb_virthub.c | 46 
> -----------------------------------------
>  4 files changed, 49 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
> index 5b4fa79..60dbeba 100644
> --- a/drivers/usb/musb/musb_core.c
> +++ b/drivers/usb/musb/musb_core.c
> @@ -922,6 +922,52 @@ static void musb_generic_disable(struct musb *musb)
>  }
>  
>  /*
> + * Program the HDRC to start (enable interrupts, dma, etc.).
> + */
> +void musb_start(struct musb *musb)
> +{
> +     void __iomem    *regs = musb->mregs;
> +     u8              devctl = musb_readb(regs, MUSB_DEVCTL);
> +
> +     dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
> +
> +     /*  Set INT enable registers, enable interrupts */
> +     musb->intrtxe = musb->epmask;
> +     musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);
> +     musb->intrrxe = musb->epmask & 0xfffe;
> +     musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);
> +     musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
> +
> +     musb_writeb(regs, MUSB_TESTMODE, 0);
> +
> +     /* put into basic highspeed mode and start session */
> +     musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
> +                     | MUSB_POWER_HSENAB
> +                     /* ENSUSPEND wedges tusb */
> +                     /* | MUSB_POWER_ENSUSPEND */
> +                );
> +
> +     musb->is_active = 0;
> +     devctl = musb_readb(regs, MUSB_DEVCTL);
> +     devctl &= ~MUSB_DEVCTL_SESSION;
> +
> +     /* session started after:
> +      * (a) ID-grounded irq, host mode;
> +      * (b) vbus present/connect IRQ, peripheral mode;
> +      * (c) peripheral initiates, using SRP
> +      */
> +     if (musb->port_mode != MUSB_PORT_MODE_HOST &&
> +                     (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
> +             musb->is_active = 1;
> +     } else {
> +             devctl |= MUSB_DEVCTL_SESSION;
> +     }
> +
> +     musb_platform_enable(musb);
> +     musb_writeb(regs, MUSB_DEVCTL, devctl);
> +}
> +
> +/*
>   * Make the HDRC stop (disable interrupts, etc.);
>   * reversible by musb_start
>   * called on gadget driver unregister
> diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
> index 65f3917..1c5bf75 100644
> --- a/drivers/usb/musb/musb_core.h
> +++ b/drivers/usb/musb/musb_core.h
> @@ -503,6 +503,7 @@ static inline void musb_configure_ep0(struct musb *musb)
>  extern const char musb_driver_name[];
>  
>  extern void musb_stop(struct musb *musb);
> +extern void musb_start(struct musb *musb);
>  
>  extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src);
>  extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst);
> diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
> index b19ed21..07bf4df 100644
> --- a/drivers/usb/musb/musb_gadget.c
> +++ b/drivers/usb/musb/musb_gadget.c
> @@ -1858,6 +1858,8 @@ static int musb_gadget_start(struct usb_gadget *g,
>       musb->xceiv->state = OTG_STATE_B_IDLE;
>       spin_unlock_irqrestore(&musb->lock, flags);
>  
> +     musb_start(musb);
> +
>       /* REVISIT:  funcall to other code, which also
>        * handles power budgeting ... this way also
>        * ensures HdrcStart is indirectly called.
> diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
> index a523950..d1d6b83 100644
> --- a/drivers/usb/musb/musb_virthub.c
> +++ b/drivers/usb/musb/musb_virthub.c
> @@ -44,52 +44,6 @@
>  
>  #include "musb_core.h"
>  
> -/*
> -* Program the HDRC to start (enable interrupts, dma, etc.).
> -*/
> -static void musb_start(struct musb *musb)
> -{
> -     void __iomem    *regs = musb->mregs;
> -     u8              devctl = musb_readb(regs, MUSB_DEVCTL);
> -
> -     dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
> -
> -     /*  Set INT enable registers, enable interrupts */
> -     musb->intrtxe = musb->epmask;
> -     musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);
> -     musb->intrrxe = musb->epmask & 0xfffe;
> -     musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);
> -     musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
> -
> -     musb_writeb(regs, MUSB_TESTMODE, 0);
> -
> -     /* put into basic highspeed mode and start session */
> -     musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
> -                                             | MUSB_POWER_HSENAB
> -                                             /* ENSUSPEND wedges tusb */
> -                                             /* | MUSB_POWER_ENSUSPEND */
> -                                             );
> -
> -     musb->is_active = 0;
> -     devctl = musb_readb(regs, MUSB_DEVCTL);
> -     devctl &= ~MUSB_DEVCTL_SESSION;
> -
> -     /* session started after:
> -      * (a) ID-grounded irq, host mode;
> -      * (b) vbus present/connect IRQ, peripheral mode;
> -      * (c) peripheral initiates, using SRP
> -      */
> -     if (musb->port_mode != MUSB_PORT_MODE_HOST &&
> -         (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
> -             musb->is_active = 1;
> -     } else {
> -             devctl |= MUSB_DEVCTL_SESSION;
> -     }
> -
> -     musb_platform_enable(musb);
> -     musb_writeb(regs, MUSB_DEVCTL, devctl);
> -}
> -
>  static void musb_port_suspend(struct musb *musb, bool do_suspend)
>  {
>       struct usb_otg  *otg = musb->xceiv->otg;
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to