diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2012-10-30 14:52:26 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2012-10-31 09:22:18 -0400 |
commit | b18d26f6ad8f00ea5f7c6a12ea52627ca3c3c6e2 (patch) | |
tree | 651526d8d433418664bcee887f6d1a60ee7946f7 | |
parent | af5ec14d40e0da1de17fcca2b41c76fae5c2cb9d (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.c | 10 | ||||
-rw-r--r-- | drivers/usb/musb/musb_core.h | 2 | ||||
-rw-r--r-- | drivers/usb/musb/musb_gadget.c | 17 | ||||
-rw-r--r-- | drivers/usb/musb/musb_host.c | 2 |
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 { | |||
288 | struct musb_context_registers { | 288 | struct 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 */ |