^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * TUSB6010 USB 2.0 OTG Dual Role controller OMAP DMA interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2006 Nokia Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Tony Lindgren <tony@atomide.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/usb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/dmaengine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "musb_core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "tusb6010.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define to_chdat(c) ((struct tusb_omap_dma_ch *)(c)->private_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define MAX_DMAREQ 5 /* REVISIT: Really 6, but req5 not OK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct tusb_dma_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) s8 dmareq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct dma_chan *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct tusb_omap_dma_ch {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct musb *musb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) void __iomem *tbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) unsigned long phys_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int epnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) u8 tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct musb_hw_ep *hw_ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct tusb_dma_data *dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct tusb_omap_dma *tusb_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) dma_addr_t dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u32 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) u16 packet_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) u16 transfer_packet_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) u32 transfer_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) u32 completed_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct tusb_omap_dma {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct dma_controller controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) void __iomem *tbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct tusb_dma_data dma_pool[MAX_DMAREQ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) unsigned multichannel:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * Allocate dmareq0 to the current channel unless it's already taken
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static inline int tusb_omap_use_shared_dmareq(struct tusb_omap_dma_ch *chdat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (reg != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) dev_dbg(chdat->musb->controller, "ep%i dmareq0 is busy for ep%i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) chdat->epnum, reg & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (chdat->tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) reg = (1 << 4) | chdat->epnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) reg = chdat->epnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static inline void tusb_omap_free_shared_dmareq(struct tusb_omap_dma_ch *chdat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if ((reg & 0xf) != chdat->epnum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) printk(KERN_ERR "ep%i trying to release dmareq0 for ep%i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) chdat->epnum, reg & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * See also musb_dma_completion in plat_uds.c and musb_g_[tx|rx]() in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * musb_gadget.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static void tusb_omap_dma_cb(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct dma_channel *channel = (struct dma_channel *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct tusb_omap_dma_ch *chdat = to_chdat(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct tusb_omap_dma *tusb_dma = chdat->tusb_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct musb *musb = chdat->musb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct device *dev = musb->controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct musb_hw_ep *hw_ep = chdat->hw_ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) void __iomem *ep_conf = hw_ep->conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) void __iomem *mbase = musb->mregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) unsigned long remaining, flags, pio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) spin_lock_irqsave(&musb->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) dev_dbg(musb->controller, "ep%i %s dma callback\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) chdat->epnum, chdat->tx ? "tx" : "rx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (chdat->tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) remaining = musb_readl(ep_conf, TUSB_EP_RX_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) remaining = TUSB_EP_CONFIG_XFR_SIZE(remaining);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (unlikely(remaining > chdat->transfer_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) dev_dbg(musb->controller, "Corrupt %s XFR_SIZE: 0x%08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) chdat->tx ? "tx" : "rx", remaining);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) remaining = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) channel->actual_len = chdat->transfer_len - remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) pio = chdat->len - channel->actual_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) dev_dbg(musb->controller, "DMA remaining %lu/%u\n", remaining, chdat->transfer_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* Transfer remaining 1 - 31 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (pio > 0 && pio < 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) dev_dbg(musb->controller, "Using PIO for remaining %lu bytes\n", pio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) buf = phys_to_virt((u32)chdat->dma_addr) + chdat->transfer_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (chdat->tx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) dma_unmap_single(dev, chdat->dma_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) chdat->transfer_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) DMA_TO_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) musb_write_fifo(hw_ep, pio, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) dma_unmap_single(dev, chdat->dma_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) chdat->transfer_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) DMA_FROM_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) musb_read_fifo(hw_ep, pio, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) channel->actual_len += pio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (!tusb_dma->multichannel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) tusb_omap_free_shared_dmareq(chdat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) channel->status = MUSB_DMA_STATUS_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) musb_dma_completion(musb, chdat->epnum, chdat->tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /* We must terminate short tx transfers manually by setting TXPKTRDY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * REVISIT: This same problem may occur with other MUSB dma as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * Easy to test with g_ether by pinging the MUSB board with ping -s54.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if ((chdat->transfer_len < chdat->packet_sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) || (chdat->transfer_len % chdat->packet_sz != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) u16 csr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (chdat->tx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) dev_dbg(musb->controller, "terminating short tx packet\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) musb_ep_select(mbase, chdat->epnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) csr = musb_readw(hw_ep->regs, MUSB_TXCSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) | MUSB_TXCSR_P_WZC_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) musb_writew(hw_ep->regs, MUSB_TXCSR, csr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) spin_unlock_irqrestore(&musb->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) u8 rndis_mode, dma_addr_t dma_addr, u32 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct tusb_omap_dma_ch *chdat = to_chdat(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct tusb_omap_dma *tusb_dma = chdat->tusb_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct musb *musb = chdat->musb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) struct device *dev = musb->controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct musb_hw_ep *hw_ep = chdat->hw_ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) void __iomem *mbase = musb->mregs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) void __iomem *ep_conf = hw_ep->conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) dma_addr_t fifo_addr = hw_ep->fifo_sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) u32 dma_remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) u16 csr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) u32 psize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct tusb_dma_data *dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct dma_async_tx_descriptor *dma_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct dma_slave_config dma_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) enum dma_transfer_direction dma_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u32 port_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * HW issue #10: Async dma will eventually corrupt the XFR_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * register which will cause missed DMA interrupt. We could try to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * use a timer for the callback, but it is unsafe as the XFR_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * register is corrupt, and we won't know if the DMA worked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (dma_addr & 0x2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * Because of HW issue #10, it seems like mixing sync DMA and async
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * PIO access can confuse the DMA. Make sure XFR_SIZE is reset before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * using the channel for DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (chdat->tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) dma_remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) dma_remaining = musb_readl(ep_conf, TUSB_EP_RX_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (dma_remaining) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) dev_dbg(musb->controller, "Busy %s dma, not using: %08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) chdat->tx ? "tx" : "rx", dma_remaining);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) chdat->transfer_len = len & ~0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (len < packet_sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) chdat->transfer_packet_sz = chdat->transfer_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) chdat->transfer_packet_sz = packet_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) dma_data = chdat->dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!tusb_dma->multichannel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (tusb_omap_use_shared_dmareq(chdat) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) dev_dbg(musb->controller, "could not get dma for ep%i\n", chdat->epnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (dma_data->dmareq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /* REVISIT: This should get blocked earlier, happens
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * with MSC ErrorRecoveryTest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) chdat->packet_sz = packet_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) chdat->len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) channel->actual_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) chdat->dma_addr = dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) channel->status = MUSB_DMA_STATUS_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* Since we're recycling dma areas, we need to clean or invalidate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (chdat->tx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) dma_dir = DMA_MEM_TO_DEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) dma_map_single(dev, phys_to_virt(dma_addr), len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) DMA_TO_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) dma_dir = DMA_DEV_TO_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) dma_map_single(dev, phys_to_virt(dma_addr), len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) DMA_FROM_DEVICE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) memset(&dma_cfg, 0, sizeof(dma_cfg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* Use 16-bit transfer if dma_addr is not 32-bit aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if ((dma_addr & 0x3) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) port_window = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) port_window = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) fifo_addr = hw_ep->fifo_async;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) dev_dbg(musb->controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) "ep%i %s dma: %pad len: %u(%u) packet_sz: %i(%i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) chdat->epnum, chdat->tx ? "tx" : "rx", &dma_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) chdat->transfer_len, len, chdat->transfer_packet_sz, packet_sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) dma_cfg.src_addr = fifo_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) dma_cfg.dst_addr = fifo_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) dma_cfg.src_port_window_size = port_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) dma_cfg.src_maxburst = port_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) dma_cfg.dst_port_window_size = port_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) dma_cfg.dst_maxburst = port_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ret = dmaengine_slave_config(dma_data->chan, &dma_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) dev_err(musb->controller, "DMA slave config failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) dma_desc = dmaengine_prep_slave_single(dma_data->chan, dma_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) chdat->transfer_len, dma_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (!dma_desc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) dev_err(musb->controller, "DMA prep_slave_single failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) dma_desc->callback = tusb_omap_dma_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) dma_desc->callback_param = channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) dmaengine_submit(dma_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) dev_dbg(musb->controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) "ep%i %s using %i-bit %s dma from %pad to %pad\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) chdat->epnum, chdat->tx ? "tx" : "rx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) dma_cfg.src_addr_width * 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) ((dma_addr & 0x3) == 0) ? "sync" : "async",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) (dma_dir == DMA_MEM_TO_DEV) ? &dma_addr : &fifo_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) (dma_dir == DMA_MEM_TO_DEV) ? &fifo_addr : &dma_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * Prepare MUSB for DMA transfer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) musb_ep_select(mbase, chdat->epnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (chdat->tx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) csr = musb_readw(hw_ep->regs, MUSB_TXCSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) csr |= (MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) | MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) csr &= ~MUSB_TXCSR_P_UNDERRUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) musb_writew(hw_ep->regs, MUSB_TXCSR, csr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) csr |= MUSB_RXCSR_DMAENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAMODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) musb_writew(hw_ep->regs, MUSB_RXCSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) csr | MUSB_RXCSR_P_WZC_BITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /* Start DMA transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) dma_async_issue_pending(dma_data->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (chdat->tx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /* Send transfer_packet_sz packets at a time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) psize &= ~0x7ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) psize |= chdat->transfer_packet_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) musb_writel(ep_conf, TUSB_EP_TX_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* Receive transfer_packet_sz packets at a time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) psize &= ~(0x7ff << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) psize |= (chdat->transfer_packet_sz << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) musb_writel(ep_conf, TUSB_EP_RX_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static int tusb_omap_dma_abort(struct dma_channel *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct tusb_omap_dma_ch *chdat = to_chdat(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (chdat->dma_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) dmaengine_terminate_all(chdat->dma_data->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) channel->status = MUSB_DMA_STATUS_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static inline int tusb_omap_dma_allocate_dmareq(struct tusb_omap_dma_ch *chdat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int i, dmareq_nr = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) for (i = 0; i < MAX_DMAREQ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) int cur = (reg & (0xf << (i * 5))) >> (i * 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (cur == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) dmareq_nr = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (dmareq_nr == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) reg |= (chdat->epnum << (dmareq_nr * 5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (chdat->tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) reg |= ((1 << 4) << (dmareq_nr * 5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) chdat->dma_data = &chdat->tusb_dma->dma_pool[dmareq_nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static inline void tusb_omap_dma_free_dmareq(struct tusb_omap_dma_ch *chdat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (!chdat || !chdat->dma_data || chdat->dma_data->dmareq < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) reg &= ~(0x1f << (chdat->dma_data->dmareq * 5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) chdat->dma_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) static struct dma_channel *dma_channel_pool[MAX_DMAREQ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static struct dma_channel *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) tusb_omap_dma_allocate(struct dma_controller *c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct musb_hw_ep *hw_ep,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) u8 tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct tusb_omap_dma *tusb_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct musb *musb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct dma_channel *channel = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) struct tusb_omap_dma_ch *chdat = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) struct tusb_dma_data *dma_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) tusb_dma = container_of(c, struct tusb_omap_dma, controller);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) musb = tusb_dma->controller.musb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /* REVISIT: Why does dmareq5 not work? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (hw_ep->epnum == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) dev_dbg(musb->controller, "Not allowing DMA for ep0 %s\n", tx ? "tx" : "rx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) for (i = 0; i < MAX_DMAREQ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) struct dma_channel *ch = dma_channel_pool[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (ch->status == MUSB_DMA_STATUS_UNKNOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) ch->status = MUSB_DMA_STATUS_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) channel = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) chdat = ch->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (!channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) chdat->musb = tusb_dma->controller.musb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) chdat->tbase = tusb_dma->tbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) chdat->hw_ep = hw_ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) chdat->epnum = hw_ep->epnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) chdat->completed_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) chdat->tusb_dma = tusb_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (tx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) chdat->tx = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) chdat->tx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) channel->max_len = 0x7fffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) channel->desired_mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) channel->actual_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (!chdat->dma_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (tusb_dma->multichannel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) ret = tusb_omap_dma_allocate_dmareq(chdat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) goto free_dmareq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) chdat->dma_data = &tusb_dma->dma_pool[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) dma_data = chdat->dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) dev_dbg(musb->controller, "ep%i %s dma: %s dmareq%i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) chdat->epnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) chdat->tx ? "tx" : "rx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) tusb_dma->multichannel ? "shared" : "dedicated",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) dma_data->dmareq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) free_dmareq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) tusb_omap_dma_free_dmareq(chdat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) dev_dbg(musb->controller, "ep%i: Could not get a DMA channel\n", chdat->epnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) channel->status = MUSB_DMA_STATUS_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) static void tusb_omap_dma_release(struct dma_channel *channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) struct tusb_omap_dma_ch *chdat = to_chdat(channel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) struct musb *musb = chdat->musb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) dev_dbg(musb->controller, "Release for ep%i\n", chdat->epnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) channel->status = MUSB_DMA_STATUS_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) dmaengine_terminate_sync(chdat->dma_data->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) tusb_omap_dma_free_dmareq(chdat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) channel = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) void tusb_dma_controller_destroy(struct dma_controller *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) struct tusb_omap_dma *tusb_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) tusb_dma = container_of(c, struct tusb_omap_dma, controller);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) for (i = 0; i < MAX_DMAREQ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct dma_channel *ch = dma_channel_pool[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (ch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) kfree(ch->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) kfree(ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) /* Free up the DMA channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (tusb_dma && tusb_dma->dma_pool[i].chan)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) dma_release_channel(tusb_dma->dma_pool[i].chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) kfree(tusb_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) EXPORT_SYMBOL_GPL(tusb_dma_controller_destroy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) static int tusb_omap_allocate_dma_pool(struct tusb_omap_dma *tusb_dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct musb *musb = tusb_dma->controller.musb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) for (i = 0; i < MAX_DMAREQ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct tusb_dma_data *dma_data = &tusb_dma->dma_pool[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * Request DMA channels:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * - one channel in case of non multichannel mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * - MAX_DMAREQ number of channels in multichannel mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (i == 0 || tusb_dma->multichannel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) char ch_name[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) sprintf(ch_name, "dmareq%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) dma_data->chan = dma_request_chan(musb->controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ch_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (IS_ERR(dma_data->chan)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) dev_err(musb->controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) "Failed to request %s\n", ch_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) ret = PTR_ERR(dma_data->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) goto dma_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) dma_data->dmareq = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) dma_data->dmareq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) dma_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) for (; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct tusb_dma_data *dma_data = &tusb_dma->dma_pool[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (dma_data->dmareq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) dma_release_channel(dma_data->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct dma_controller *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) tusb_dma_controller_create(struct musb *musb, void __iomem *base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) void __iomem *tbase = musb->ctrl_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) struct tusb_omap_dma *tusb_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* REVISIT: Get dmareq lines used from board-*.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) musb_writel(musb->ctrl_base, TUSB_DMA_INT_MASK, 0x7fffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) musb_writel(musb->ctrl_base, TUSB_DMA_EP_MAP, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) musb_writel(tbase, TUSB_DMA_REQ_CONF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) TUSB_DMA_REQ_CONF_BURST_SIZE(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) | TUSB_DMA_REQ_CONF_DMA_REQ_EN(0x3f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) | TUSB_DMA_REQ_CONF_DMA_REQ_ASSER(2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) tusb_dma = kzalloc(sizeof(struct tusb_omap_dma), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (!tusb_dma)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) tusb_dma->controller.musb = musb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) tusb_dma->tbase = musb->ctrl_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) tusb_dma->controller.channel_alloc = tusb_omap_dma_allocate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) tusb_dma->controller.channel_release = tusb_omap_dma_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) tusb_dma->controller.channel_program = tusb_omap_dma_program;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) tusb_dma->controller.channel_abort = tusb_omap_dma_abort;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (musb->tusb_revision >= TUSB_REV_30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) tusb_dma->multichannel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) for (i = 0; i < MAX_DMAREQ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) struct dma_channel *ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) struct tusb_omap_dma_ch *chdat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) ch = kzalloc(sizeof(struct dma_channel), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (!ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) dma_channel_pool[i] = ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) chdat = kzalloc(sizeof(struct tusb_omap_dma_ch), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (!chdat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) ch->status = MUSB_DMA_STATUS_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) ch->private_data = chdat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (tusb_omap_allocate_dma_pool(tusb_dma))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return &tusb_dma->controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) musb_dma_controller_destroy(&tusb_dma->controller);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) EXPORT_SYMBOL_GPL(tusb_dma_controller_create);