Commit 2001f67e47ee3b0d822e2c738da5c4c33a31a7ea

Authored by George Cherian
Committed by Kishon Vijay Abraham I
1 parent 0bde8afc3a

Revert "usb: musb: musb_cppi41: Revert the Advisory 1.0.13 workaround"

Reverting the Advisory 1.0.13 leads to functional issues when multiple
Mass Storage devices are connected. Especially when more than 3
Mass Storage disks are connected it fails to mount the disks reliably.

This reverts commit c424ef3e2beb89488e7e597446b4c6bc8f1852c5.

Signed-off-by: George Cherian <george.cherian@ti.com>
Reported-by: Roger Quadros <rogerq@ti.com>

Showing 1 changed file with 79 additions and 17 deletions Side-by-side Diff

drivers/usb/musb/musb_cppi41.c
... ... @@ -31,6 +31,7 @@
31 31 u8 port_num;
32 32 u8 is_tx;
33 33 u8 is_allocated;
  34 + u8 usb_toggle;
34 35  
35 36 dma_addr_t buf_addr;
36 37 u32 total_len;
... ... @@ -55,6 +56,50 @@
55 56 u32 auto_req;
56 57 };
57 58  
  59 +static void save_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
  60 +{
  61 + u16 csr;
  62 + u8 toggle;
  63 +
  64 + if (cppi41_channel->is_tx)
  65 + return;
  66 + if (!is_host_active(cppi41_channel->controller->musb))
  67 + return;
  68 +
  69 + csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR);
  70 + toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;
  71 +
  72 + cppi41_channel->usb_toggle = toggle;
  73 +}
  74 +
  75 +static void update_rx_toggle(struct cppi41_dma_channel *cppi41_channel)
  76 +{
  77 + u16 csr;
  78 + u8 toggle;
  79 +
  80 + if (cppi41_channel->is_tx)
  81 + return;
  82 + if (!is_host_active(cppi41_channel->controller->musb))
  83 + return;
  84 +
  85 + csr = musb_readw(cppi41_channel->hw_ep->regs, MUSB_RXCSR);
  86 + toggle = csr & MUSB_RXCSR_H_DATATOGGLE ? 1 : 0;
  87 +
  88 + /*
  89 + * AM335x Advisory 1.0.13: Due to internal synchronisation error the
  90 + * data toggle may reset from DATA1 to DATA0 during receiving data from
  91 + * more than one endpoint.
  92 + */
  93 + if (!toggle && toggle == cppi41_channel->usb_toggle) {
  94 + csr |= MUSB_RXCSR_H_DATATOGGLE | MUSB_RXCSR_H_WR_DATATOGGLE;
  95 + musb_writew(cppi41_channel->hw_ep->regs, MUSB_RXCSR, csr);
  96 + dev_dbg(cppi41_channel->controller->musb->controller,
  97 + "Restoring DATA1 toggle.\n");
  98 + }
  99 +
  100 + cppi41_channel->usb_toggle = toggle;
  101 +}
  102 +
58 103 static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep)
59 104 {
60 105 u8 epnum = hw_ep->epnum;
... ... @@ -217,6 +262,8 @@
217 262 hw_ep->epnum, cppi41_channel->transferred,
218 263 cppi41_channel->total_len);
219 264  
  265 + update_rx_toggle(cppi41_channel);
  266 +
220 267 if (cppi41_channel->transferred == cppi41_channel->total_len ||
221 268 transferred < cppi41_channel->packet_sz)
222 269 cppi41_channel->prog_len = 0;
... ... @@ -347,6 +394,7 @@
347 394 struct dma_async_tx_descriptor *dma_desc;
348 395 enum dma_transfer_direction direction;
349 396 struct musb *musb = cppi41_channel->controller->musb;
  397 + unsigned use_gen_rndis = 0;
350 398  
351 399 dev_dbg(musb->controller,
352 400 "configure ep%d/%x packet_sz=%d, mode=%d, dma_addr=0x%llx, len=%d is_tx=%d\n",
353 401  
354 402  
355 403  
356 404  
... ... @@ -359,26 +407,39 @@
359 407 cppi41_channel->transferred = 0;
360 408 cppi41_channel->packet_sz = packet_sz;
361 409  
362   - /* RNDIS mode */
363   - if (len > packet_sz) {
364   - musb_writel(musb->ctrl_base,
365   - RNDIS_REG(cppi41_channel->port_num), len);
366   - /* gen rndis */
367   - cppi41_set_dma_mode(cppi41_channel,
368   - EP_MODE_DMA_GEN_RNDIS);
  410 + /*
  411 + * Due to AM335x' Advisory 1.0.13 we are not allowed to transfer more
  412 + * than max packet size at a time.
  413 + */
  414 + if (cppi41_channel->is_tx)
  415 + use_gen_rndis = 1;
369 416  
370   - /* auto req */
371   - cppi41_set_autoreq_mode(cppi41_channel,
  417 + if (use_gen_rndis) {
  418 + /* RNDIS mode */
  419 + if (len > packet_sz) {
  420 + musb_writel(musb->ctrl_base,
  421 + RNDIS_REG(cppi41_channel->port_num), len);
  422 + /* gen rndis */
  423 + cppi41_set_dma_mode(cppi41_channel,
  424 + EP_MODE_DMA_GEN_RNDIS);
  425 +
  426 + /* auto req */
  427 + cppi41_set_autoreq_mode(cppi41_channel,
372 428 EP_MODE_AUTOREG_ALL_NEOP);
373   - } else {
374   - musb_writel(musb->ctrl_base,
375   - RNDIS_REG(cppi41_channel->port_num), 0);
376   - cppi41_set_dma_mode(cppi41_channel,
377   - EP_MODE_DMA_TRANSPARENT);
378   - cppi41_set_autoreq_mode(cppi41_channel,
  429 + } else {
  430 + musb_writel(musb->ctrl_base,
  431 + RNDIS_REG(cppi41_channel->port_num), 0);
  432 + cppi41_set_dma_mode(cppi41_channel,
  433 + EP_MODE_DMA_TRANSPARENT);
  434 + cppi41_set_autoreq_mode(cppi41_channel,
379 435 EP_MODE_AUTOREG_NONE);
  436 + }
  437 + } else {
  438 + /* fallback mode */
  439 + cppi41_set_dma_mode(cppi41_channel, EP_MODE_DMA_TRANSPARENT);
  440 + cppi41_set_autoreq_mode(cppi41_channel, EP_MODE_AUTOREG_NONE);
  441 + len = min_t(u32, packet_sz, len);
380 442 }
381   -
382 443 cppi41_channel->prog_len = len;
383 444 direction = cppi41_channel->is_tx ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
384 445 dma_desc = dmaengine_prep_slave_single(dc, dma_addr, len, direction,
... ... @@ -390,6 +451,7 @@
390 451 dma_desc->callback_param = channel;
391 452 cppi41_channel->cookie = dma_desc->tx_submit(dma_desc);
392 453  
  454 + save_rx_toggle(cppi41_channel);
393 455 dma_async_issue_pending(dc);
394 456 return true;
395 457 }