usb: musb: Perform only write access on MUSB_INTRTXE
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Tue, 30 Oct 2012 18:52:26 +0000 (19:52 +0100)
committerFelipe Balbi <balbi@ti.com>
Wed, 31 Oct 2012 13:22:18 +0000 (15:22 +0200)
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_INTRTXE results in an 32bit read
access which also reads INTRRX and therefore may lose interrupts.
This patch uses a shadow register of MUSB_INTRTXE so we only perform
write access to it.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musb_host.c

index 7ff1986e5e529a621d2f713d241e5a8c8d1a2e35..25a0d8e1be515a1a6683116851bfac41b0917b1e 100644 (file)
@@ -724,7 +724,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                if (is_peripheral_active(musb)) {
                        /* REVISIT HNP; just force disconnect */
                }
-               musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask);
+               musb->intrtxe = musb->epmask;
+               musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe);
                musb->intrrxe = musb->epmask & 0xfffe;
                musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe);
                musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7);
@@ -947,7 +948,8 @@ void musb_start(struct musb *musb)
        dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
 
        /*  Set INT enable registers, enable interrupts */
-       musb_writew(regs, MUSB_INTRTXE, musb->epmask);
+       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);
@@ -987,6 +989,7 @@ static void musb_generic_disable(struct musb *musb)
 
        /* disable interrupts */
        musb_writeb(mbase, MUSB_INTRUSBE, 0);
+       musb->intrtxe = 0;
        musb_writew(mbase, MUSB_INTRTXE, 0);
        musb->intrrxe = 0;
        musb_writew(mbase, MUSB_INTRRXE, 0);
@@ -2124,7 +2127,6 @@ static void musb_save_context(struct musb *musb)
        musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
        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.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);
@@ -2197,7 +2199,7 @@ static void musb_restore_context(struct musb *musb)
        musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
        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_INTRTXE, musb->intrtxe);
        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);
index 60b92cbdc7f7556ea89a9dabf3194b3b97bc6983..0cef3ceb52c33a891a6c2c214a7ac283af7f444e 100644 (file)
@@ -288,7 +288,6 @@ struct musb_csr_regs {
 struct musb_context_registers {
 
        u8 power;
-       u16 intrtxe;
        u8 intrusbe;
        u16 frame;
        u8 index, testmode;
@@ -314,6 +313,7 @@ struct musb {
        u16                     hwvers;
 
        u16                     intrrxe;
+       u16                     intrtxe;
 /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
 #define MUSB_PORT_STAT_RESUME  (1 << 31)
 
index bb684f0f790db36f2508e2cd76b08ca8179667ce..28b9790e84ea9f225b59f36d226529716571778f 100644 (file)
@@ -1068,7 +1068,6 @@ static int musb_gadget_enable(struct usb_ep *ep,
         */
        musb_ep_select(mbase, epnum);
        if (usb_endpoint_dir_in(desc)) {
-               u16 int_txe = musb_readw(mbase, MUSB_INTRTXE);
 
                if (hw_ep->is_shared_fifo)
                        musb_ep->is_in = 1;
@@ -1080,8 +1079,8 @@ static int musb_gadget_enable(struct usb_ep *ep,
                        goto fail;
                }
 
-               int_txe |= (1 << epnum);
-               musb_writew(mbase, MUSB_INTRTXE, int_txe);
+               musb->intrtxe |= (1 << epnum);
+               musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe);
 
                /* REVISIT if can_bulk_split(), use by updating "tmp";
                 * likewise high bandwidth periodic tx
@@ -1208,9 +1207,8 @@ static int musb_gadget_disable(struct usb_ep *ep)
 
        /* zero the endpoint sizes */
        if (musb_ep->is_in) {
-               u16 int_txe = musb_readw(musb->mregs, MUSB_INTRTXE);
-               int_txe &= ~(1 << epnum);
-               musb_writew(musb->mregs, MUSB_INTRTXE, int_txe);
+               musb->intrtxe &= ~(1 << epnum);
+               musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe);
                musb_writew(epio, MUSB_TXMAXP, 0);
        } else {
                musb->intrrxe &= ~(1 << epnum);
@@ -1530,7 +1528,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
        void __iomem    *epio = musb->endpoints[epnum].regs;
        void __iomem    *mbase;
        unsigned long   flags;
-       u16             csr, int_txe;
+       u16             csr;
 
        mbase = musb->mregs;
 
@@ -1538,8 +1536,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
        musb_ep_select(mbase, (u8) epnum);
 
        /* disable interrupts */
-       int_txe = musb_readw(mbase, MUSB_INTRTXE);
-       musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
+       musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe & ~(1 << epnum));
 
        if (musb_ep->is_in) {
                csr = musb_readw(epio, MUSB_TXCSR);
@@ -1563,7 +1560,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
        }
 
        /* re-enable interrupt */
-       musb_writew(mbase, MUSB_INTRTXE, int_txe);
+       musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe);
        spin_unlock_irqrestore(&musb->lock, flags);
 }
 
index 3df6a76b851dbefc91c6d5488570f9d53813a59b..e9f0fd9ddd2d05284283ee3448785984cc760c10 100644 (file)
@@ -740,7 +740,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
                csr = musb_readw(epio, MUSB_TXCSR);
 
                /* disable interrupt in case we flush */
-               int_txe = musb_readw(mbase, MUSB_INTRTXE);
+               int_txe = musb->intrtxe;
                musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
 
                /* general endpoint setup */