Commit c461db2ad66b153b0b54450e2241bfe086b5314f
1 parent
d6c21f4ebb
Exists in
smarc-ti-linux-3.12.y
Fix MUSB DMA Bug
Showing 6 changed files with 40 additions and 68 deletions Side-by-side Diff
drivers/dma/cppi41.c
... | ... | @@ -86,6 +86,9 @@ |
86 | 86 | |
87 | 87 | #define USBSS_IRQ_PD_COMP (1 << 2) |
88 | 88 | |
89 | +/* Packet Descriptor */ | |
90 | +#define PD2_ZERO_LENGTH (1 << 19) | |
91 | + | |
89 | 92 | struct cppi41_channel { |
90 | 93 | struct dma_chan chan; |
91 | 94 | struct dma_async_tx_descriptor txd; |
... | ... | @@ -307,8 +310,7 @@ |
307 | 310 | __iormb(); |
308 | 311 | |
309 | 312 | while (val) { |
310 | - u32 desc; | |
311 | - | |
313 | + u32 desc, len; | |
312 | 314 | q_num = __fls(val); |
313 | 315 | val &= ~(1 << q_num); |
314 | 316 | q_num += 32 * i; |
... | ... | @@ -322,6 +324,12 @@ |
322 | 324 | c->residue = pd_trans_len(c->desc->pd6) - |
323 | 325 | pd_trans_len(c->desc->pd0); |
324 | 326 | |
327 | + if (c->desc->pd2 & PD2_ZERO_LENGTH) | |
328 | + len = 0; | |
329 | + else | |
330 | + len = pd_trans_len(c->desc->pd0); | |
331 | + | |
332 | + c->residue = pd_trans_len(c->desc->pd6) - len; | |
325 | 333 | dma_cookie_complete(&c->txd); |
326 | 334 | c->txd.callback(c->txd.callback_param); |
327 | 335 | } |
drivers/usb/musb/musb_core.c
... | ... | @@ -1541,7 +1541,7 @@ |
1541 | 1541 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); |
1542 | 1542 | |
1543 | 1543 | dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n", |
1544 | - (devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral", | |
1544 | + is_host_active(musb) ? "host" : "peripheral", | |
1545 | 1545 | musb->int_usb, musb->int_tx, musb->int_rx); |
1546 | 1546 | |
1547 | 1547 | /* the core can interrupt us for multiple reasons; docs have |
... | ... | @@ -1555,7 +1555,7 @@ |
1555 | 1555 | |
1556 | 1556 | /* handle endpoint 0 first */ |
1557 | 1557 | if (musb->int_tx & 1) { |
1558 | - if (devctl & MUSB_DEVCTL_HM) | |
1558 | + if (is_host_active(musb)) | |
1559 | 1559 | retval |= musb_h_ep0_irq(musb); |
1560 | 1560 | else |
1561 | 1561 | retval |= musb_g_ep0_irq(musb); |
... | ... | @@ -1569,7 +1569,7 @@ |
1569 | 1569 | /* musb_ep_select(musb->mregs, ep_num); */ |
1570 | 1570 | /* REVISIT just retval = ep->rx_irq(...) */ |
1571 | 1571 | retval = IRQ_HANDLED; |
1572 | - if (devctl & MUSB_DEVCTL_HM) | |
1572 | + if (is_host_active(musb)) | |
1573 | 1573 | musb_host_rx(musb, ep_num); |
1574 | 1574 | else |
1575 | 1575 | musb_g_rx(musb, ep_num); |
... | ... | @@ -1587,7 +1587,7 @@ |
1587 | 1587 | /* musb_ep_select(musb->mregs, ep_num); */ |
1588 | 1588 | /* REVISIT just retval |= ep->tx_irq(...) */ |
1589 | 1589 | retval = IRQ_HANDLED; |
1590 | - if (devctl & MUSB_DEVCTL_HM) | |
1590 | + if (is_host_active(musb)) | |
1591 | 1591 | musb_host_tx(musb, ep_num); |
1592 | 1592 | else |
1593 | 1593 | musb_g_tx(musb, ep_num); |
1594 | 1594 | |
... | ... | @@ -1618,15 +1618,13 @@ |
1618 | 1618 | |
1619 | 1619 | void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit) |
1620 | 1620 | { |
1621 | - u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | |
1622 | - | |
1623 | 1621 | /* called with controller lock already held */ |
1624 | 1622 | |
1625 | 1623 | if (!epnum) { |
1626 | 1624 | #ifndef CONFIG_USB_TUSB_OMAP_DMA |
1627 | 1625 | if (!is_cppi_enabled()) { |
1628 | 1626 | /* endpoint 0 */ |
1629 | - if (devctl & MUSB_DEVCTL_HM) | |
1627 | + if (is_host_active(musb)) | |
1630 | 1628 | musb_h_ep0_irq(musb); |
1631 | 1629 | else |
1632 | 1630 | musb_g_ep0_irq(musb); |
1633 | 1631 | |
... | ... | @@ -1635,13 +1633,13 @@ |
1635 | 1633 | } else { |
1636 | 1634 | /* endpoints 1..15 */ |
1637 | 1635 | if (transmit) { |
1638 | - if (devctl & MUSB_DEVCTL_HM) | |
1636 | + if (is_host_active(musb)) | |
1639 | 1637 | musb_host_tx(musb, epnum); |
1640 | 1638 | else |
1641 | 1639 | musb_g_tx(musb, epnum); |
1642 | 1640 | } else { |
1643 | 1641 | /* receive */ |
1644 | - if (devctl & MUSB_DEVCTL_HM) | |
1642 | + if (is_host_active(musb)) | |
1645 | 1643 | musb_host_rx(musb, epnum); |
1646 | 1644 | else |
1647 | 1645 | musb_g_rx(musb, epnum); |
drivers/usb/musb/musb_cppi41.c
... | ... | @@ -39,7 +39,6 @@ |
39 | 39 | u32 transferred; |
40 | 40 | u32 packet_sz; |
41 | 41 | struct list_head tx_check; |
42 | - struct work_struct dma_completion; | |
43 | 42 | }; |
44 | 43 | |
45 | 44 | #define MUSB_DMA_NUM_CHANNELS 15 |
46 | 45 | |
47 | 46 | |
... | ... | @@ -74,15 +73,18 @@ |
74 | 73 | |
75 | 74 | static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel) |
76 | 75 | { |
76 | + struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep; | |
77 | + struct musb *musb = hw_ep->musb; | |
77 | 78 | u16 csr; |
78 | 79 | u8 toggle; |
79 | 80 | |
80 | 81 | if (cppi41_channel->is_tx) |
81 | 82 | return; |
82 | - if (!is_host_active(cppi41_channel->controller->musb)) | |
83 | + if (!is_host_active(musb)) | |
83 | 84 | return; |
84 | 85 | |
85 | - csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR); | |
86 | + musb_ep_select(musb->mregs, hw_ep->epnum); | |
87 | + csr = musb_readw(hw_ep->regs, MUSB_RXCSR); | |
86 | 88 | toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0; |
87 | 89 | |
88 | 90 | /* |
89 | 91 | |
... | ... | @@ -107,24 +109,13 @@ |
107 | 109 | void __iomem *epio = musb->endpoints[epnum].regs; |
108 | 110 | u16 csr; |
109 | 111 | |
112 | + musb_ep_select(musb->mregs, hw_ep->epnum); | |
110 | 113 | csr = musb_readw(epio, MUSB_TXCSR); |
111 | 114 | if (csr & MUSB_TXCSR_TXPKTRDY) |
112 | 115 | return false; |
113 | 116 | return true; |
114 | 117 | } |
115 | 118 | |
116 | -static bool is_isoc(struct musb_hw_ep *hw_ep, bool in) | |
117 | -{ | |
118 | - if (in && hw_ep->in_qh) { | |
119 | - if (hw_ep->in_qh->type == USB_ENDPOINT_XFER_ISOC) | |
120 | - return true; | |
121 | - } else if (hw_ep->out_qh) { | |
122 | - if (hw_ep->out_qh->type == USB_ENDPOINT_XFER_ISOC) | |
123 | - return true; | |
124 | - } | |
125 | - return false; | |
126 | -} | |
127 | - | |
128 | 119 | static void cppi41_dma_callback(void *private_data); |
129 | 120 | |
130 | 121 | static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel) |
... | ... | @@ -139,6 +130,7 @@ |
139 | 130 | cppi41_channel->channel.actual_len = |
140 | 131 | cppi41_channel->transferred; |
141 | 132 | cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE; |
133 | + cppi41_channel->channel.rx_packet_done = true; | |
142 | 134 | musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx); |
143 | 135 | } else { |
144 | 136 | /* next iteration, reload */ |
... | ... | @@ -172,6 +164,7 @@ |
172 | 164 | dma_async_issue_pending(dc); |
173 | 165 | |
174 | 166 | if (!cppi41_channel->is_tx) { |
167 | + musb_ep_select(musb->mregs, hw_ep->epnum); | |
175 | 168 | csr = musb_readw(epio, MUSB_RXCSR); |
176 | 169 | csr |= MUSB_RXCSR_H_REQPKT; |
177 | 170 | musb_writew(epio, MUSB_RXCSR, csr); |
... | ... | @@ -179,32 +172,6 @@ |
179 | 172 | } |
180 | 173 | } |
181 | 174 | |
182 | -static void cppi_trans_done_work(struct work_struct *work) | |
183 | -{ | |
184 | - unsigned long flags; | |
185 | - struct cppi41_dma_channel *cppi41_channel = | |
186 | - container_of(work, struct cppi41_dma_channel, dma_completion); | |
187 | - struct cppi41_dma_controller *controller = cppi41_channel->controller; | |
188 | - struct musb *musb = controller->musb; | |
189 | - struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep; | |
190 | - bool empty; | |
191 | - | |
192 | - if (!cppi41_channel->is_tx && is_isoc(hw_ep, 1)) { | |
193 | - spin_lock_irqsave(&musb->lock, flags); | |
194 | - cppi41_trans_done(cppi41_channel); | |
195 | - spin_unlock_irqrestore(&musb->lock, flags); | |
196 | - } else { | |
197 | - empty = musb_is_tx_fifo_empty(hw_ep); | |
198 | - if (empty) { | |
199 | - spin_lock_irqsave(&musb->lock, flags); | |
200 | - cppi41_trans_done(cppi41_channel); | |
201 | - spin_unlock_irqrestore(&musb->lock, flags); | |
202 | - } else { | |
203 | - schedule_work(&cppi41_channel->dma_completion); | |
204 | - } | |
205 | - } | |
206 | -} | |
207 | - | |
208 | 175 | static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer) |
209 | 176 | { |
210 | 177 | struct cppi41_dma_controller *controller; |
... | ... | @@ -268,14 +235,6 @@ |
268 | 235 | transferred < cppi41_channel->packet_sz) |
269 | 236 | cppi41_channel->prog_len = 0; |
270 | 237 | |
271 | - if (!cppi41_channel->is_tx) { | |
272 | - if (is_isoc(hw_ep, 1)) | |
273 | - schedule_work(&cppi41_channel->dma_completion); | |
274 | - else | |
275 | - cppi41_trans_done(cppi41_channel); | |
276 | - goto out; | |
277 | - } | |
278 | - | |
279 | 238 | empty = musb_is_tx_fifo_empty(hw_ep); |
280 | 239 | if (empty) { |
281 | 240 | cppi41_trans_done(cppi41_channel); |
... | ... | @@ -312,10 +271,6 @@ |
312 | 271 | goto out; |
313 | 272 | } |
314 | 273 | } |
315 | - if (is_isoc(hw_ep, 0)) { | |
316 | - schedule_work(&cppi41_channel->dma_completion); | |
317 | - goto out; | |
318 | - } | |
319 | 274 | list_add_tail(&cppi41_channel->tx_check, |
320 | 275 | &controller->early_tx_list); |
321 | 276 | if (!hrtimer_is_queued(&controller->early_tx)) { |
... | ... | @@ -452,6 +407,7 @@ |
452 | 407 | dma_desc->callback = cppi41_dma_callback; |
453 | 408 | dma_desc->callback_param = channel; |
454 | 409 | cppi41_channel->cookie = dma_desc->tx_submit(dma_desc); |
410 | + cppi41_channel->channel.rx_packet_done = false; | |
455 | 411 | |
456 | 412 | save_rx_toggle(cppi41_channel); |
457 | 413 | dma_async_issue_pending(dc); |
... | ... | @@ -674,8 +630,7 @@ |
674 | 630 | cppi41_channel->port_num = port; |
675 | 631 | cppi41_channel->is_tx = is_tx; |
676 | 632 | INIT_LIST_HEAD(&cppi41_channel->tx_check); |
677 | - INIT_WORK(&cppi41_channel->dma_completion, | |
678 | - cppi_trans_done_work); | |
633 | + | |
679 | 634 | musb_dma = &cppi41_channel->channel; |
680 | 635 | musb_dma->private_data = cppi41_channel; |
681 | 636 | musb_dma->status = MUSB_DMA_STATUS_FREE; |
drivers/usb/musb/musb_dma.h
drivers/usb/musb/musb_host.c
... | ... | @@ -121,7 +121,7 @@ |
121 | 121 | if (csr != lastcsr) |
122 | 122 | dev_dbg(musb->controller, "Host TX FIFONOTEMPTY csr: %02x\n", csr); |
123 | 123 | lastcsr = csr; |
124 | - csr |= MUSB_TXCSR_FLUSHFIFO; | |
124 | + csr |= MUSB_TXCSR_FLUSHFIFO | MUSB_TXCSR_TXPKTRDY; | |
125 | 125 | musb_writew(epio, MUSB_TXCSR, csr); |
126 | 126 | csr = musb_readw(epio, MUSB_TXCSR); |
127 | 127 | if (WARN(retries-- < 1, |
... | ... | @@ -1739,7 +1739,8 @@ |
1739 | 1739 | /* done if urb buffer is full or short packet is recd */ |
1740 | 1740 | done = (urb->actual_length + xfer_len >= |
1741 | 1741 | urb->transfer_buffer_length |
1742 | - || dma->actual_len < qh->maxpacket); | |
1742 | + || dma->actual_len < qh->maxpacket | |
1743 | + || dma->rx_packet_done); | |
1743 | 1744 | } |
1744 | 1745 | |
1745 | 1746 | /* send IN token for next packet, without AUTOREQ */ |
drivers/usb/phy/phy-am335x-control.c
... | ... | @@ -3,6 +3,7 @@ |
3 | 3 | #include <linux/err.h> |
4 | 4 | #include <linux/of.h> |
5 | 5 | #include <linux/io.h> |
6 | +#include <linux/delay.h> | |
6 | 7 | |
7 | 8 | struct phy_control { |
8 | 9 | void (*phy_power)(struct phy_control *phy_ctrl, u32 id, bool on); |
... | ... | @@ -90,6 +91,14 @@ |
90 | 91 | } |
91 | 92 | |
92 | 93 | writel(val, usb_ctrl->phy_reg + reg); |
94 | + | |
95 | + /* | |
96 | + * Give the PHY ~1ms to complete the power up operation. | |
97 | + * Tests have shown unstable behaviour if other USB PHY related | |
98 | + * registers are written too shortly after such a transition. | |
99 | + */ | |
100 | + if (on) | |
101 | + mdelay(1); | |
93 | 102 | } |
94 | 103 | |
95 | 104 | static const struct phy_control ctrl_am335x = { |