From af5ec14d40e0da1de17fcca2b41c76fae5c2cb9d Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 30 Oct 2012 19:52:25 +0100 Subject: usb: musb: Perform only write access on MUSB_INTRRXE This is part of the workaround for AM35x advisory Advisory 1.1.20. The advisory says that the IPSS bridge can't handle 8 & 16 bit read access. An 16bit read access to MUSB_INTRRXE results in an 32bit read access which also reads INTRUSB and therefore may lose interrupts. This patch uses a shadow register of MUSB_INTRRXE so we only perform write access to it. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 10 ++++++---- drivers/usb/musb/musb_core.h | 3 ++- drivers/usb/musb/musb_gadget.c | 10 ++++------ 3 files changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index d156fe8bebfa..7ff1986e5e52 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -725,7 +725,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, /* REVISIT HNP; just force disconnect */ } musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask); - musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe); + musb->intrrxe = musb->epmask & 0xfffe; + musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe); musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7); musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED |USB_PORT_STAT_HIGH_SPEED @@ -947,7 +948,8 @@ void musb_start(struct musb *musb) /* Set INT enable registers, enable interrupts */ musb_writew(regs, MUSB_INTRTXE, musb->epmask); - musb_writew(regs, MUSB_INTRRXE, musb->epmask & 0xfffe); + musb->intrrxe = musb->epmask & 0xfffe; + musb_writew(regs, MUSB_INTRRXE, musb->intrrxe); musb_writeb(regs, MUSB_INTRUSBE, 0xf7); musb_writeb(regs, MUSB_TESTMODE, 0); @@ -986,6 +988,7 @@ static void musb_generic_disable(struct musb *musb) /* disable interrupts */ musb_writeb(mbase, MUSB_INTRUSBE, 0); musb_writew(mbase, MUSB_INTRTXE, 0); + musb->intrrxe = 0; musb_writew(mbase, MUSB_INTRRXE, 0); /* off */ @@ -2122,7 +2125,6 @@ static void musb_save_context(struct musb *musb) musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs); musb->context.power = musb_readb(musb_base, MUSB_POWER); musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE); - musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE); musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE); musb->context.index = musb_readb(musb_base, MUSB_INDEX); musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL); @@ -2196,7 +2198,7 @@ static void musb_restore_context(struct musb *musb) musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl); musb_writeb(musb_base, MUSB_POWER, musb->context.power); musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe); - musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe); + musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe); musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe); musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index c158aacd6de8..60b92cbdc7f7 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -288,7 +288,7 @@ struct musb_csr_regs { struct musb_context_registers { u8 power; - u16 intrtxe, intrrxe; + u16 intrtxe; u8 intrusbe; u16 frame; u8 index, testmode; @@ -313,6 +313,7 @@ struct musb { struct work_struct irq_work; u16 hwvers; + u16 intrrxe; /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */ #define MUSB_PORT_STAT_RESUME (1 << 31) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index b430f158e668..bb684f0f790d 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1108,7 +1108,6 @@ static int musb_gadget_enable(struct usb_ep *ep, musb_writew(regs, MUSB_TXCSR, csr); } else { - u16 int_rxe = musb_readw(mbase, MUSB_INTRRXE); if (hw_ep->is_shared_fifo) musb_ep->is_in = 0; @@ -1120,8 +1119,8 @@ static int musb_gadget_enable(struct usb_ep *ep, goto fail; } - int_rxe |= (1 << epnum); - musb_writew(mbase, MUSB_INTRRXE, int_rxe); + musb->intrrxe |= (1 << epnum); + musb_writew(mbase, MUSB_INTRRXE, musb->intrrxe); /* REVISIT if can_bulk_combine() use by updating "tmp" * likewise high bandwidth periodic rx @@ -1214,9 +1213,8 @@ static int musb_gadget_disable(struct usb_ep *ep) musb_writew(musb->mregs, MUSB_INTRTXE, int_txe); musb_writew(epio, MUSB_TXMAXP, 0); } else { - u16 int_rxe = musb_readw(musb->mregs, MUSB_INTRRXE); - int_rxe &= ~(1 << epnum); - musb_writew(musb->mregs, MUSB_INTRRXE, int_rxe); + musb->intrrxe &= ~(1 << epnum); + musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe); musb_writew(epio, MUSB_RXMAXP, 0); } -- cgit v1.2.3-55-g7522