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 <bige...@linutronix.de>
---
 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(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 84a46b5..3065618 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -695,7 +695,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
@@ -917,7 +918,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);
@@ -956,6 +958,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 */
@@ -2092,7 +2095,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);
@@ -2166,7 +2168,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 4e9cf4e..3e179ad 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 b430f15..bb684f0 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);
        }
 
-- 
1.7.10.4

--
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