Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22c7ef0a authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'fixes-for-v3.12-rc5' of...

Merge tag 'fixes-for-v3.12-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb

 into usb-linus

Pull USB gadget fixes from Felipe:

usb: musb: fix for v3.12-rc

A single patch fixing musb start when using peripheral
only configurations. It turns out that musb_start() needs
to be called for peripheral too, so that function is
factored out of musb_virthub.c and into musb_core.c since
it's shared for both roles.

Signed-of-by: default avatarFelipe Balbi <balbi@ti.com>
parents d0e639c9 001dd84a
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -921,6 +921,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
+1 −0
Original line number Diff line number Diff line
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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.
+0 −46
Original line number Diff line number Diff line
@@ -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;