Lines Matching +full:pio +full:- +full:transfer
1 // SPDX-License-Identifier: GPL-2.0
13 #include <linux/dma-mapping.h>
20 #define to_chdat(c) ((struct tusb_omap_dma_ch *)(c)->private_data)
63 u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP); in tusb_omap_use_shared_dmareq()
66 dev_dbg(chdat->musb->controller, "ep%i dmareq0 is busy for ep%i\n", in tusb_omap_use_shared_dmareq()
67 chdat->epnum, reg & 0xf); in tusb_omap_use_shared_dmareq()
68 return -EAGAIN; in tusb_omap_use_shared_dmareq()
71 if (chdat->tx) in tusb_omap_use_shared_dmareq()
72 reg = (1 << 4) | chdat->epnum; in tusb_omap_use_shared_dmareq()
74 reg = chdat->epnum; in tusb_omap_use_shared_dmareq()
76 musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg); in tusb_omap_use_shared_dmareq()
83 u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP); in tusb_omap_free_shared_dmareq()
85 if ((reg & 0xf) != chdat->epnum) { in tusb_omap_free_shared_dmareq()
87 chdat->epnum, reg & 0xf); in tusb_omap_free_shared_dmareq()
90 musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, 0); in tusb_omap_free_shared_dmareq()
101 struct tusb_omap_dma *tusb_dma = chdat->tusb_dma; in tusb_omap_dma_cb()
102 struct musb *musb = chdat->musb; in tusb_omap_dma_cb()
103 struct device *dev = musb->controller; in tusb_omap_dma_cb()
104 struct musb_hw_ep *hw_ep = chdat->hw_ep; in tusb_omap_dma_cb()
105 void __iomem *ep_conf = hw_ep->conf; in tusb_omap_dma_cb()
106 void __iomem *mbase = musb->mregs; in tusb_omap_dma_cb()
107 unsigned long remaining, flags, pio; in tusb_omap_dma_cb() local
109 spin_lock_irqsave(&musb->lock, flags); in tusb_omap_dma_cb()
111 dev_dbg(musb->controller, "ep%i %s dma callback\n", in tusb_omap_dma_cb()
112 chdat->epnum, chdat->tx ? "tx" : "rx"); in tusb_omap_dma_cb()
114 if (chdat->tx) in tusb_omap_dma_cb()
122 if (unlikely(remaining > chdat->transfer_len)) { in tusb_omap_dma_cb()
123 dev_dbg(musb->controller, "Corrupt %s XFR_SIZE: 0x%08lx\n", in tusb_omap_dma_cb()
124 chdat->tx ? "tx" : "rx", remaining); in tusb_omap_dma_cb()
128 channel->actual_len = chdat->transfer_len - remaining; in tusb_omap_dma_cb()
129 pio = chdat->len - channel->actual_len; in tusb_omap_dma_cb()
131 dev_dbg(musb->controller, "DMA remaining %lu/%u\n", remaining, chdat->transfer_len); in tusb_omap_dma_cb()
133 /* Transfer remaining 1 - 31 bytes */ in tusb_omap_dma_cb()
134 if (pio > 0 && pio < 32) { in tusb_omap_dma_cb()
137 dev_dbg(musb->controller, "Using PIO for remaining %lu bytes\n", pio); in tusb_omap_dma_cb()
138 buf = phys_to_virt((u32)chdat->dma_addr) + chdat->transfer_len; in tusb_omap_dma_cb()
139 if (chdat->tx) { in tusb_omap_dma_cb()
140 dma_unmap_single(dev, chdat->dma_addr, in tusb_omap_dma_cb()
141 chdat->transfer_len, in tusb_omap_dma_cb()
143 musb_write_fifo(hw_ep, pio, buf); in tusb_omap_dma_cb()
145 dma_unmap_single(dev, chdat->dma_addr, in tusb_omap_dma_cb()
146 chdat->transfer_len, in tusb_omap_dma_cb()
148 musb_read_fifo(hw_ep, pio, buf); in tusb_omap_dma_cb()
150 channel->actual_len += pio; in tusb_omap_dma_cb()
153 if (!tusb_dma->multichannel) in tusb_omap_dma_cb()
156 channel->status = MUSB_DMA_STATUS_FREE; in tusb_omap_dma_cb()
158 musb_dma_completion(musb, chdat->epnum, chdat->tx); in tusb_omap_dma_cb()
162 * Easy to test with g_ether by pinging the MUSB board with ping -s54. in tusb_omap_dma_cb()
164 if ((chdat->transfer_len < chdat->packet_sz) in tusb_omap_dma_cb()
165 || (chdat->transfer_len % chdat->packet_sz != 0)) { in tusb_omap_dma_cb()
168 if (chdat->tx) { in tusb_omap_dma_cb()
169 dev_dbg(musb->controller, "terminating short tx packet\n"); in tusb_omap_dma_cb()
170 musb_ep_select(mbase, chdat->epnum); in tusb_omap_dma_cb()
171 csr = musb_readw(hw_ep->regs, MUSB_TXCSR); in tusb_omap_dma_cb()
174 musb_writew(hw_ep->regs, MUSB_TXCSR, csr); in tusb_omap_dma_cb()
178 spin_unlock_irqrestore(&musb->lock, flags); in tusb_omap_dma_cb()
185 struct tusb_omap_dma *tusb_dma = chdat->tusb_dma; in tusb_omap_dma_program()
186 struct musb *musb = chdat->musb; in tusb_omap_dma_program()
187 struct device *dev = musb->controller; in tusb_omap_dma_program()
188 struct musb_hw_ep *hw_ep = chdat->hw_ep; in tusb_omap_dma_program()
189 void __iomem *mbase = musb->mregs; in tusb_omap_dma_program()
190 void __iomem *ep_conf = hw_ep->conf; in tusb_omap_dma_program()
191 dma_addr_t fifo_addr = hw_ep->fifo_sync; in tusb_omap_dma_program()
216 * PIO access can confuse the DMA. Make sure XFR_SIZE is reset before in tusb_omap_dma_program()
219 if (chdat->tx) in tusb_omap_dma_program()
226 dev_dbg(musb->controller, "Busy %s dma, not using: %08x\n", in tusb_omap_dma_program()
227 chdat->tx ? "tx" : "rx", dma_remaining); in tusb_omap_dma_program()
231 chdat->transfer_len = len & ~0x1f; in tusb_omap_dma_program()
234 chdat->transfer_packet_sz = chdat->transfer_len; in tusb_omap_dma_program()
236 chdat->transfer_packet_sz = packet_sz; in tusb_omap_dma_program()
238 dma_data = chdat->dma_data; in tusb_omap_dma_program()
239 if (!tusb_dma->multichannel) { in tusb_omap_dma_program()
241 dev_dbg(musb->controller, "could not get dma for ep%i\n", chdat->epnum); in tusb_omap_dma_program()
244 if (dma_data->dmareq < 0) { in tusb_omap_dma_program()
253 chdat->packet_sz = packet_sz; in tusb_omap_dma_program()
254 chdat->len = len; in tusb_omap_dma_program()
255 channel->actual_len = 0; in tusb_omap_dma_program()
256 chdat->dma_addr = dma_addr; in tusb_omap_dma_program()
257 channel->status = MUSB_DMA_STATUS_BUSY; in tusb_omap_dma_program()
260 if (chdat->tx) { in tusb_omap_dma_program()
272 /* Use 16-bit transfer if dma_addr is not 32-bit aligned */ in tusb_omap_dma_program()
282 fifo_addr = hw_ep->fifo_async; in tusb_omap_dma_program()
285 dev_dbg(musb->controller, in tusb_omap_dma_program()
287 chdat->epnum, chdat->tx ? "tx" : "rx", &dma_addr, in tusb_omap_dma_program()
288 chdat->transfer_len, len, chdat->transfer_packet_sz, packet_sz); in tusb_omap_dma_program()
297 ret = dmaengine_slave_config(dma_data->chan, &dma_cfg); in tusb_omap_dma_program()
299 dev_err(musb->controller, "DMA slave config failed: %d\n", ret); in tusb_omap_dma_program()
303 dma_desc = dmaengine_prep_slave_single(dma_data->chan, dma_addr, in tusb_omap_dma_program()
304 chdat->transfer_len, dma_dir, in tusb_omap_dma_program()
307 dev_err(musb->controller, "DMA prep_slave_single failed\n"); in tusb_omap_dma_program()
311 dma_desc->callback = tusb_omap_dma_cb; in tusb_omap_dma_program()
312 dma_desc->callback_param = channel; in tusb_omap_dma_program()
315 dev_dbg(musb->controller, in tusb_omap_dma_program()
316 "ep%i %s using %i-bit %s dma from %pad to %pad\n", in tusb_omap_dma_program()
317 chdat->epnum, chdat->tx ? "tx" : "rx", in tusb_omap_dma_program()
324 * Prepare MUSB for DMA transfer in tusb_omap_dma_program()
326 musb_ep_select(mbase, chdat->epnum); in tusb_omap_dma_program()
327 if (chdat->tx) { in tusb_omap_dma_program()
328 csr = musb_readw(hw_ep->regs, MUSB_TXCSR); in tusb_omap_dma_program()
332 musb_writew(hw_ep->regs, MUSB_TXCSR, csr); in tusb_omap_dma_program()
334 csr = musb_readw(hw_ep->regs, MUSB_RXCSR); in tusb_omap_dma_program()
337 musb_writew(hw_ep->regs, MUSB_RXCSR, in tusb_omap_dma_program()
341 /* Start DMA transfer */ in tusb_omap_dma_program()
342 dma_async_issue_pending(dma_data->chan); in tusb_omap_dma_program()
344 if (chdat->tx) { in tusb_omap_dma_program()
348 psize |= chdat->transfer_packet_sz; in tusb_omap_dma_program()
352 TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len)); in tusb_omap_dma_program()
357 psize |= (chdat->transfer_packet_sz << 16); in tusb_omap_dma_program()
361 TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len)); in tusb_omap_dma_program()
371 if (chdat->dma_data) in tusb_omap_dma_abort()
372 dmaengine_terminate_all(chdat->dma_data->chan); in tusb_omap_dma_abort()
374 channel->status = MUSB_DMA_STATUS_FREE; in tusb_omap_dma_abort()
381 u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP); in tusb_omap_dma_allocate_dmareq()
382 int i, dmareq_nr = -1; in tusb_omap_dma_allocate_dmareq()
392 if (dmareq_nr == -1) in tusb_omap_dma_allocate_dmareq()
393 return -EAGAIN; in tusb_omap_dma_allocate_dmareq()
395 reg |= (chdat->epnum << (dmareq_nr * 5)); in tusb_omap_dma_allocate_dmareq()
396 if (chdat->tx) in tusb_omap_dma_allocate_dmareq()
398 musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg); in tusb_omap_dma_allocate_dmareq()
400 chdat->dma_data = &chdat->tusb_dma->dma_pool[dmareq_nr]; in tusb_omap_dma_allocate_dmareq()
409 if (!chdat || !chdat->dma_data || chdat->dma_data->dmareq < 0) in tusb_omap_dma_free_dmareq()
412 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP); in tusb_omap_dma_free_dmareq()
413 reg &= ~(0x1f << (chdat->dma_data->dmareq * 5)); in tusb_omap_dma_free_dmareq()
414 musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg); in tusb_omap_dma_free_dmareq()
416 chdat->dma_data = NULL; in tusb_omap_dma_free_dmareq()
434 musb = tusb_dma->controller.musb; in tusb_omap_dma_allocate()
437 if (hw_ep->epnum == 0) { in tusb_omap_dma_allocate()
438 dev_dbg(musb->controller, "Not allowing DMA for ep0 %s\n", tx ? "tx" : "rx"); in tusb_omap_dma_allocate()
444 if (ch->status == MUSB_DMA_STATUS_UNKNOWN) { in tusb_omap_dma_allocate()
445 ch->status = MUSB_DMA_STATUS_FREE; in tusb_omap_dma_allocate()
447 chdat = ch->private_data; in tusb_omap_dma_allocate()
455 chdat->musb = tusb_dma->controller.musb; in tusb_omap_dma_allocate()
456 chdat->tbase = tusb_dma->tbase; in tusb_omap_dma_allocate()
457 chdat->hw_ep = hw_ep; in tusb_omap_dma_allocate()
458 chdat->epnum = hw_ep->epnum; in tusb_omap_dma_allocate()
459 chdat->completed_len = 0; in tusb_omap_dma_allocate()
460 chdat->tusb_dma = tusb_dma; in tusb_omap_dma_allocate()
462 chdat->tx = 1; in tusb_omap_dma_allocate()
464 chdat->tx = 0; in tusb_omap_dma_allocate()
466 channel->max_len = 0x7fffffff; in tusb_omap_dma_allocate()
467 channel->desired_mode = 0; in tusb_omap_dma_allocate()
468 channel->actual_len = 0; in tusb_omap_dma_allocate()
470 if (!chdat->dma_data) { in tusb_omap_dma_allocate()
471 if (tusb_dma->multichannel) { in tusb_omap_dma_allocate()
476 chdat->dma_data = &tusb_dma->dma_pool[0]; in tusb_omap_dma_allocate()
480 dma_data = chdat->dma_data; in tusb_omap_dma_allocate()
482 dev_dbg(musb->controller, "ep%i %s dma: %s dmareq%i\n", in tusb_omap_dma_allocate()
483 chdat->epnum, in tusb_omap_dma_allocate()
484 chdat->tx ? "tx" : "rx", in tusb_omap_dma_allocate()
485 tusb_dma->multichannel ? "shared" : "dedicated", in tusb_omap_dma_allocate()
486 dma_data->dmareq); in tusb_omap_dma_allocate()
493 dev_dbg(musb->controller, "ep%i: Could not get a DMA channel\n", chdat->epnum); in tusb_omap_dma_allocate()
494 channel->status = MUSB_DMA_STATUS_UNKNOWN; in tusb_omap_dma_allocate()
502 struct musb *musb = chdat->musb; in tusb_omap_dma_release()
504 dev_dbg(musb->controller, "Release for ep%i\n", chdat->epnum); in tusb_omap_dma_release()
506 channel->status = MUSB_DMA_STATUS_UNKNOWN; in tusb_omap_dma_release()
508 dmaengine_terminate_sync(chdat->dma_data->chan); in tusb_omap_dma_release()
523 kfree(ch->private_data); in tusb_dma_controller_destroy()
528 if (tusb_dma && tusb_dma->dma_pool[i].chan) in tusb_dma_controller_destroy()
529 dma_release_channel(tusb_dma->dma_pool[i].chan); in tusb_dma_controller_destroy()
538 struct musb *musb = tusb_dma->controller.musb; in tusb_omap_allocate_dma_pool()
543 struct tusb_dma_data *dma_data = &tusb_dma->dma_pool[i]; in tusb_omap_allocate_dma_pool()
547 * - one channel in case of non multichannel mode in tusb_omap_allocate_dma_pool()
548 * - MAX_DMAREQ number of channels in multichannel mode in tusb_omap_allocate_dma_pool()
550 if (i == 0 || tusb_dma->multichannel) { in tusb_omap_allocate_dma_pool()
554 dma_data->chan = dma_request_chan(musb->controller, in tusb_omap_allocate_dma_pool()
556 if (IS_ERR(dma_data->chan)) { in tusb_omap_allocate_dma_pool()
557 dev_err(musb->controller, in tusb_omap_allocate_dma_pool()
559 ret = PTR_ERR(dma_data->chan); in tusb_omap_allocate_dma_pool()
563 dma_data->dmareq = i; in tusb_omap_allocate_dma_pool()
565 dma_data->dmareq = -1; in tusb_omap_allocate_dma_pool()
572 for (; i >= 0; i--) { in tusb_omap_allocate_dma_pool()
573 struct tusb_dma_data *dma_data = &tusb_dma->dma_pool[i]; in tusb_omap_allocate_dma_pool()
575 if (dma_data->dmareq >= 0) in tusb_omap_allocate_dma_pool()
576 dma_release_channel(dma_data->chan); in tusb_omap_allocate_dma_pool()
585 void __iomem *tbase = musb->ctrl_base; in tusb_dma_controller_create()
589 /* REVISIT: Get dmareq lines used from board-*.c */ in tusb_dma_controller_create()
591 musb_writel(musb->ctrl_base, TUSB_DMA_INT_MASK, 0x7fffffff); in tusb_dma_controller_create()
592 musb_writel(musb->ctrl_base, TUSB_DMA_EP_MAP, 0); in tusb_dma_controller_create()
603 tusb_dma->controller.musb = musb; in tusb_dma_controller_create()
604 tusb_dma->tbase = musb->ctrl_base; in tusb_dma_controller_create()
606 tusb_dma->controller.channel_alloc = tusb_omap_dma_allocate; in tusb_dma_controller_create()
607 tusb_dma->controller.channel_release = tusb_omap_dma_release; in tusb_dma_controller_create()
608 tusb_dma->controller.channel_program = tusb_omap_dma_program; in tusb_dma_controller_create()
609 tusb_dma->controller.channel_abort = tusb_omap_dma_abort; in tusb_dma_controller_create()
611 if (musb->tusb_revision >= TUSB_REV_30) in tusb_dma_controller_create()
612 tusb_dma->multichannel = 1; in tusb_dma_controller_create()
628 ch->status = MUSB_DMA_STATUS_UNKNOWN; in tusb_dma_controller_create()
629 ch->private_data = chdat; in tusb_dma_controller_create()
635 return &tusb_dma->controller; in tusb_dma_controller_create()
638 musb_dma_controller_destroy(&tusb_dma->controller); in tusb_dma_controller_create()