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 <[email protected]>
> Cc: Peter Korsgaard <[email protected]>
> Signed-off-by: Sebastian Andrzej Siewior <[email protected]>
Looks good to me - successfully tested on my host-only board.
Tested-by: Daniel Mack <[email protected]>
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html