aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2012-10-30 14:52:26 -0400
committerFelipe Balbi <balbi@ti.com>2012-10-31 09:22:18 -0400
commitb18d26f6ad8f00ea5f7c6a12ea52627ca3c3c6e2 (patch)
tree651526d8d433418664bcee887f6d1a60ee7946f7
parentaf5ec14d40e0da1de17fcca2b41c76fae5c2cb9d (diff)
usb: musb: Perform only write access on MUSB_INTRTXE
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>
-rw-r--r--drivers/usb/musb/musb_core.c10
-rw-r--r--drivers/usb/musb/musb_core.h2
-rw-r--r--drivers/usb/musb/musb_gadget.c17
-rw-r--r--drivers/usb/musb/musb_host.c2
4 files changed, 15 insertions, 16 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 7ff1986e5e52..25a0d8e1be51 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -724,7 +724,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
724 if (is_peripheral_active(musb)) { 724 if (is_peripheral_active(musb)) {
725 /* REVISIT HNP; just force disconnect */ 725 /* REVISIT HNP; just force disconnect */
726 } 726 }
727 musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask); 727 musb->intrtxe = musb->epmask;
728 musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe);
728 musb->intrrxe = musb->epmask & 0xfffe; 729 musb->intrrxe = musb->epmask & 0xfffe;
729 musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe); 730 musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe);
730 musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7); 731 musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7);
@@ -947,7 +948,8 @@ void musb_start(struct musb *musb)
947 dev_dbg(musb->controller, "<== devctl %02x\n", devctl); 948 dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
948 949
949 /* Set INT enable registers, enable interrupts */ 950 /* Set INT enable registers, enable interrupts */
950 musb_writew(regs, MUSB_INTRTXE, musb->epmask); 951 musb->intrtxe = musb->epmask;
952 musb_writew(regs, MUSB_INTRTXE, musb->intrtxe);
951 musb->intrrxe = musb->epmask & 0xfffe; 953 musb->intrrxe = musb->epmask & 0xfffe;
952 musb_writew(regs, MUSB_INTRRXE, musb->intrrxe); 954 musb_writew(regs, MUSB_INTRRXE, musb->intrrxe);
953 musb_writeb(regs, MUSB_INTRUSBE, 0xf7); 955 musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
@@ -987,6 +989,7 @@ static void musb_generic_disable(struct musb *musb)
987 989
988 /* disable interrupts */ 990 /* disable interrupts */
989 musb_writeb(mbase, MUSB_INTRUSBE, 0); 991 musb_writeb(mbase, MUSB_INTRUSBE, 0);
992 musb->intrtxe = 0;
990 musb_writew(mbase, MUSB_INTRTXE, 0); 993 musb_writew(mbase, MUSB_INTRTXE, 0);
991 musb->intrrxe = 0; 994 musb->intrrxe = 0;
992 musb_writew(mbase, MUSB_INTRRXE, 0); 995 musb_writew(mbase, MUSB_INTRRXE, 0);
@@ -2124,7 +2127,6 @@ static void musb_save_context(struct musb *musb)
2124 musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE); 2127 musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE);
2125 musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs); 2128 musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs);
2126 musb->context.power = musb_readb(musb_base, MUSB_POWER); 2129 musb->context.power = musb_readb(musb_base, MUSB_POWER);
2127 musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE);
2128 musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE); 2130 musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE);
2129 musb->context.index = musb_readb(musb_base, MUSB_INDEX); 2131 musb->context.index = musb_readb(musb_base, MUSB_INDEX);
2130 musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL); 2132 musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
@@ -2197,7 +2199,7 @@ static void musb_restore_context(struct musb *musb)
2197 musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode); 2199 musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
2198 musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl); 2200 musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
2199 musb_writeb(musb_base, MUSB_POWER, musb->context.power); 2201 musb_writeb(musb_base, MUSB_POWER, musb->context.power);
2200 musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe); 2202 musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe);
2201 musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe); 2203 musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe);
2202 musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe); 2204 musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);
2203 musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl); 2205 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 60b92cbdc7f7..0cef3ceb52c3 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -288,7 +288,6 @@ struct musb_csr_regs {
288struct musb_context_registers { 288struct musb_context_registers {
289 289
290 u8 power; 290 u8 power;
291 u16 intrtxe;
292 u8 intrusbe; 291 u8 intrusbe;
293 u16 frame; 292 u16 frame;
294 u8 index, testmode; 293 u8 index, testmode;
@@ -314,6 +313,7 @@ struct musb {
314 u16 hwvers; 313 u16 hwvers;
315 314
316 u16 intrrxe; 315 u16 intrrxe;
316 u16 intrtxe;
317/* this hub status bit is reserved by USB 2.0 and not seen by usbcore */ 317/* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
318#define MUSB_PORT_STAT_RESUME (1 << 31) 318#define MUSB_PORT_STAT_RESUME (1 << 31)
319 319
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index bb684f0f790d..28b9790e84ea 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -1068,7 +1068,6 @@ static int musb_gadget_enable(struct usb_ep *ep,
1068 */ 1068 */
1069 musb_ep_select(mbase, epnum); 1069 musb_ep_select(mbase, epnum);
1070 if (usb_endpoint_dir_in(desc)) { 1070 if (usb_endpoint_dir_in(desc)) {
1071 u16 int_txe = musb_readw(mbase, MUSB_INTRTXE);
1072 1071
1073 if (hw_ep->is_shared_fifo) 1072 if (hw_ep->is_shared_fifo)
1074 musb_ep->is_in = 1; 1073 musb_ep->is_in = 1;
@@ -1080,8 +1079,8 @@ static int musb_gadget_enable(struct usb_ep *ep,
1080 goto fail; 1079 goto fail;
1081 } 1080 }
1082 1081
1083 int_txe |= (1 << epnum); 1082 musb->intrtxe |= (1 << epnum);
1084 musb_writew(mbase, MUSB_INTRTXE, int_txe); 1083 musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe);
1085 1084
1086 /* REVISIT if can_bulk_split(), use by updating "tmp"; 1085 /* REVISIT if can_bulk_split(), use by updating "tmp";
1087 * likewise high bandwidth periodic tx 1086 * likewise high bandwidth periodic tx
@@ -1208,9 +1207,8 @@ static int musb_gadget_disable(struct usb_ep *ep)
1208 1207
1209 /* zero the endpoint sizes */ 1208 /* zero the endpoint sizes */
1210 if (musb_ep->is_in) { 1209 if (musb_ep->is_in) {
1211 u16 int_txe = musb_readw(musb->mregs, MUSB_INTRTXE); 1210 musb->intrtxe &= ~(1 << epnum);
1212 int_txe &= ~(1 << epnum); 1211 musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe);
1213 musb_writew(musb->mregs, MUSB_INTRTXE, int_txe);
1214 musb_writew(epio, MUSB_TXMAXP, 0); 1212 musb_writew(epio, MUSB_TXMAXP, 0);
1215 } else { 1213 } else {
1216 musb->intrrxe &= ~(1 << epnum); 1214 musb->intrrxe &= ~(1 << epnum);
@@ -1530,7 +1528,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
1530 void __iomem *epio = musb->endpoints[epnum].regs; 1528 void __iomem *epio = musb->endpoints[epnum].regs;
1531 void __iomem *mbase; 1529 void __iomem *mbase;
1532 unsigned long flags; 1530 unsigned long flags;
1533 u16 csr, int_txe; 1531 u16 csr;
1534 1532
1535 mbase = musb->mregs; 1533 mbase = musb->mregs;
1536 1534
@@ -1538,8 +1536,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
1538 musb_ep_select(mbase, (u8) epnum); 1536 musb_ep_select(mbase, (u8) epnum);
1539 1537
1540 /* disable interrupts */ 1538 /* disable interrupts */
1541 int_txe = musb_readw(mbase, MUSB_INTRTXE); 1539 musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe & ~(1 << epnum));
1542 musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
1543 1540
1544 if (musb_ep->is_in) { 1541 if (musb_ep->is_in) {
1545 csr = musb_readw(epio, MUSB_TXCSR); 1542 csr = musb_readw(epio, MUSB_TXCSR);
@@ -1563,7 +1560,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
1563 } 1560 }
1564 1561
1565 /* re-enable interrupt */ 1562 /* re-enable interrupt */
1566 musb_writew(mbase, MUSB_INTRTXE, int_txe); 1563 musb_writew(mbase, MUSB_INTRTXE, musb->intrtxe);
1567 spin_unlock_irqrestore(&musb->lock, flags); 1564 spin_unlock_irqrestore(&musb->lock, flags);
1568} 1565}
1569 1566
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 3df6a76b851d..e9f0fd9ddd2d 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -740,7 +740,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
740 csr = musb_readw(epio, MUSB_TXCSR); 740 csr = musb_readw(epio, MUSB_TXCSR);
741 741
742 /* disable interrupt in case we flush */ 742 /* disable interrupt in case we flush */
743 int_txe = musb_readw(mbase, MUSB_INTRTXE); 743 int_txe = musb->intrtxe;
744 musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum)); 744 musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
745 745
746 /* general endpoint setup */ 746 /* general endpoint setup */