/* Context: controller irqlocked */ static void cppi_dump_rx(int level, struct cppi_channel *c, const char *tag) { void __iomem *base = c->controller->mregs; struct cppi_rx_stateram __iomem *rx = c->state_ram; musb_ep_select(base, c->index + 1); musb_dbg(c->controller->controller.musb, "RX DMA%d%s: %d left, csr %04x, " "%08x H%08x S%08x C%08x, " "B%08x L%08x %08x .. %08x", c->index, tag, musb_readl(c->controller->tibase, DAVINCI_RXCPPI_BUFCNT0_REG + 4 * c->index), musb_readw(c->hw_ep->regs, MUSB_RXCSR), musb_readl(&rx->rx_skipbytes, 0), musb_readl(&rx->rx_head, 0), musb_readl(&rx->rx_sop, 0), musb_readl(&rx->rx_current, 0), musb_readl(&rx->rx_buf_current, 0), musb_readl(&rx->rx_len_len, 0), musb_readl(&rx->rx_cnt_cnt, 0), musb_readl(&rx->rx_complete, 0) ); }
/* Context: controller irqlocked */ static void cppi_dump_tx(int level, struct cppi_channel *c, const char *tag) { void __iomem *base = c->controller->mregs; struct cppi_tx_stateram __iomem *tx = c->state_ram; musb_ep_select(base, c->index + 1); musb_dbg(c->controller->controller.musb, "TX DMA%d%s: csr %04x, " "H%08x S%08x C%08x %08x, " "F%08x L%08x .. %08x", c->index, tag, musb_readw(c->hw_ep->regs, MUSB_TXCSR), musb_readl(&tx->tx_head, 0), musb_readl(&tx->tx_buf, 0), musb_readl(&tx->tx_current, 0), musb_readl(&tx->tx_buf_current, 0), musb_readl(&tx->tx_info, 0), musb_readl(&tx->tx_rem_len, 0), /* dummy/unused word 6 */ musb_readl(&tx->tx_complete, 0) ); }
static int sunxi_musb_enable(struct musb *musb) { int ret; pr_debug("%s():\n", __func__); musb_ep_select(musb->mregs, 0); musb_writeb(musb->mregs, MUSB_FADDR, 0); if (enabled) return 0; /* select PIO mode */ musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0); if (is_host_enabled(musb)) { ret = sunxi_usb_phy_vbus_detect(0); if (ret == 1) { printf("A charger is plugged into the OTG: "); return -ENODEV; } ret = sunxi_usb_phy_id_detect(0); if (ret == 1) { printf("No host cable detected: "); return -ENODEV; } sunxi_usb_phy_power_on(0); /* port power on */ } USBC_ForceVbusValidToHigh(musb->mregs); enabled = true; return 0; }
static void musb_sysdma_completion(int lch, u16 ch_status, void *data) { u32 addr; unsigned long flags; struct dma_channel *channel; struct musb_dma_channel *musb_channel = (struct musb_dma_channel *) data; struct musb_dma_controller *controller = musb_channel->controller; struct musb *musb = controller->private_data; void __iomem *mbase = controller->base; channel = &musb_channel->channel; DBG(2, "lch = 0x%d, ch_status = 0x%x\n", lch, ch_status); spin_lock_irqsave(&musb->lock, flags); if (musb_channel->transmit) addr = (u32) omap_get_dma_src_pos(musb_channel->sysdma_channel); else addr = (u32) omap_get_dma_dst_pos(musb_channel->sysdma_channel); if (musb_channel->len == 0) channel->actual_len = 0; else channel->actual_len = addr - musb_channel->start_addr; DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n", channel, musb_channel->start_addr, addr, channel->actual_len, musb_channel->len, (channel->actual_len < musb_channel->len) ? "=> reconfig 0 " : " => complete"); channel->status = MUSB_DMA_STATUS_FREE; /* completed */ if ((musb_channel->transmit) && (channel->desired_mode == 0) && (channel->actual_len == musb_channel->max_packet_sz)) { u8 epnum = musb_channel->epnum; int offset = MUSB_EP_OFFSET(musb, epnum, MUSB_TXCSR); u16 txcsr; /* * The programming guide says that we * must clear DMAENAB before DMAMODE. */ musb_ep_select(musb, mbase, epnum); txcsr = musb_readw(mbase, offset); txcsr |= MUSB_TXCSR_TXPKTRDY; musb_writew(mbase, offset, txcsr); } musb_dma_completion(musb, musb_channel->epnum, musb_channel->transmit); spin_unlock_irqrestore(&musb->lock, flags); return; }
void musb_tx_zlp_qmu(struct musb *musb, u32 ep_num) { /* sent ZLP through PIO */ void __iomem *epio = musb->endpoints[ep_num].regs; void __iomem *mbase = musb->mregs; unsigned long timeout = jiffies + HZ; int is_timeout = 1; u16 csr; QMU_WARN("TX ZLP direct sent\n"); musb_ep_select(mbase, ep_num); /* disable dma for pio */ csr = musb_readw(epio, MUSB_TXCSR); csr &= ~MUSB_TXCSR_DMAENAB; musb_writew(epio, MUSB_TXCSR, csr); /* TXPKTRDY */ csr = musb_readw(epio, MUSB_TXCSR); csr |= MUSB_TXCSR_TXPKTRDY; musb_writew(epio, MUSB_TXCSR, csr); /* wait ZLP sent */ while (time_before_eq(jiffies, timeout)) { csr = musb_readw(epio, MUSB_TXCSR); if (!(csr & MUSB_TXCSR_TXPKTRDY)) { is_timeout = 0; break; } } /* re-enable dma for qmu */ csr = musb_readw(epio, MUSB_TXCSR); csr |= MUSB_TXCSR_DMAENAB; musb_writew(epio, MUSB_TXCSR, csr); if (is_timeout) { QMU_ERR("TX ZLP sent fail???\n"); } QMU_WARN("TX ZLP sent done\n"); }
static irqreturn_t dma_controller_irq(int irq, void *private_data) { struct musb_dma_controller *controller = private_data; struct musb *musb = controller->private_data; struct musb_dma_channel *musb_channel; struct dma_channel *channel; void __iomem *mbase = controller->base; irqreturn_t retval = IRQ_NONE; unsigned long flags; u8 bchannel; u8 int_hsdma; u32 addr; u16 csr, count; spin_lock_irqsave(&musb->lock, flags); int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR); if (!int_hsdma) { DBG(2, "spurious DMA irq\n"); for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) { musb_channel = (struct musb_dma_channel *) &(controller->channel[bchannel]); channel = &musb_channel->channel; if (channel->status == MUSB_DMA_STATUS_BUSY) { count = musb_readw(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT)); if (count == 0) int_hsdma |= (1 << bchannel); } } DBG(2, "int_hsdma = 0x%x\n", int_hsdma); if (!int_hsdma) goto done; } for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) { if (int_hsdma & (1 << bchannel)) { musb_channel = (struct musb_dma_channel *) &(controller->channel[bchannel]); channel = &musb_channel->channel; csr = musb_readw(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL)); if (csr & (1 << MUSB_HSDMA_BUSERROR_SHIFT)) { musb_channel->channel.status = MUSB_DMA_STATUS_BUS_ABORT; } else { u8 devctl; addr = musb_read_hsdma_addr(mbase, bchannel); channel->actual_len = addr - musb_channel->start_addr; DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n", channel, musb_channel->start_addr, addr, channel->actual_len, musb_channel->len, (channel->actual_len < musb_channel->len) ? "=> reconfig 0" : "=> complete"); devctl = musb_readb(mbase, MUSB_DEVCTL); channel->status = MUSB_DMA_STATUS_FREE; if (musb_channel->transmit) controller->tx_active &= ~(1 << bchannel); else controller->rx_active &= ~(1 << bchannel); /* completed */ if ((devctl & MUSB_DEVCTL_HM) && (musb_channel->transmit) && ((channel->desired_mode == 0) || (channel->actual_len & (musb_channel->max_packet_sz - 1))) ) { u8 epnum = musb_channel->epnum; int offset = MUSB_EP_OFFSET(epnum, MUSB_TXCSR); u16 txcsr; /* * The programming guide says that we * must clear DMAENAB before DMAMODE. */ musb_ep_select(mbase, epnum); txcsr = musb_readw(mbase, offset); txcsr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_AUTOSET); musb_writew(mbase, offset, txcsr); /* Send out the packet */ txcsr &= ~MUSB_TXCSR_DMAMODE; txcsr |= MUSB_TXCSR_TXPKTRDY; musb_writew(mbase, offset, txcsr); } musb_dma_completion(musb, musb_channel->epnum, musb_channel->transmit); } } } #ifdef CONFIG_BLACKFIN /* Clear DMA interrup flags */ musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma); #endif retval = IRQ_HANDLED; done: spin_unlock_irqrestore(&musb->lock, flags); return retval; }
/* * Context: controller irqlocked, endpoint selected */ static int cppi_channel_abort(struct dma_channel *channel) { struct cppi_channel *cppi_ch; struct cppi *controller; void __iomem *mbase; void __iomem *tibase; void __iomem *regs; u32 value; struct cppi_descriptor *queue; cppi_ch = container_of(channel, struct cppi_channel, channel); controller = cppi_ch->controller; switch (channel->status) { case MUSB_DMA_STATUS_BUS_ABORT: case MUSB_DMA_STATUS_CORE_ABORT: /* from RX or TX fault irq handler */ case MUSB_DMA_STATUS_BUSY: /* the hardware needs shutting down */ regs = cppi_ch->hw_ep->regs; break; case MUSB_DMA_STATUS_UNKNOWN: case MUSB_DMA_STATUS_FREE: return 0; default: return -EINVAL; } if (!cppi_ch->transmit && cppi_ch->head) cppi_dump_rxq(3, "/abort", cppi_ch); mbase = controller->mregs; tibase = controller->tibase; queue = cppi_ch->head; cppi_ch->head = NULL; cppi_ch->tail = NULL; /* REVISIT should rely on caller having done this, * and caller should rely on us not changing it. * peripheral code is safe ... check host too. */ musb_ep_select(mbase, cppi_ch->index + 1); if (cppi_ch->transmit) { struct cppi_tx_stateram __iomem *tx_ram; /* REVISIT put timeouts on these controller handshakes */ cppi_dump_tx(6, cppi_ch, " (teardown)"); /* teardown DMA engine then usb core */ do { value = musb_readl(tibase, DAVINCI_TXCPPI_TEAR_REG); } while (!(value & CPPI_TEAR_READY)); musb_writel(tibase, DAVINCI_TXCPPI_TEAR_REG, cppi_ch->index); tx_ram = cppi_ch->state_ram; do { value = musb_readl(&tx_ram->tx_complete, 0); } while (0xFFFFFFFC != value); /* FIXME clean up the transfer state ... here? * the completion routine should get called with * an appropriate status code. */ value = musb_readw(regs, MUSB_TXCSR); value &= ~MUSB_TXCSR_DMAENAB; value |= MUSB_TXCSR_FLUSHFIFO; musb_writew(regs, MUSB_TXCSR, value); musb_writew(regs, MUSB_TXCSR, value); /* * 1. Write to completion Ptr value 0x1(bit 0 set) * (write back mode) * 2. Wait for abort interrupt and then put the channel in * compare mode by writing 1 to the tx_complete register. */ cppi_reset_tx(tx_ram, 1); cppi_ch->head = NULL; musb_writel(&tx_ram->tx_complete, 0, 1); cppi_dump_tx(5, cppi_ch, " (done teardown)"); /* REVISIT tx side _should_ clean up the same way * as the RX side ... this does no cleanup at all! */ } else /* RX */ { u16 csr; /* NOTE: docs don't guarantee any of this works ... we * expect that if the usb core stops telling the cppi core * to pull more data from it, then it'll be safe to flush * current RX DMA state iff any pending fifo transfer is done. */ core_rxirq_disable(tibase, cppi_ch->index + 1); /* for host, ensure ReqPkt is never set again */ if (is_host_active(cppi_ch->controller->controller.musb)) { value = musb_readl(tibase, DAVINCI_AUTOREQ_REG); value &= ~((0x3) << (cppi_ch->index * 2)); musb_writel(tibase, DAVINCI_AUTOREQ_REG, value); } csr = musb_readw(regs, MUSB_RXCSR); /* for host, clear (just) ReqPkt at end of current packet(s) */ if (is_host_active(cppi_ch->controller->controller.musb)) { csr |= MUSB_RXCSR_H_WZC_BITS; csr &= ~MUSB_RXCSR_H_REQPKT; } else csr |= MUSB_RXCSR_P_WZC_BITS; /* clear dma enable */ csr &= ~(MUSB_RXCSR_DMAENAB); musb_writew(regs, MUSB_RXCSR, csr); csr = musb_readw(regs, MUSB_RXCSR); /* Quiesce: wait for current dma to finish (if not cleanup). * We can't use bit zero of stateram->rx_sop, since that * refers to an entire "DMA packet" not just emptying the * current fifo. Most segments need multiple usb packets. */ if (channel->status == MUSB_DMA_STATUS_BUSY) udelay(50); /* scan the current list, reporting any data that was * transferred and acking any IRQ */ cppi_rx_scan(controller, cppi_ch->index); /* clobber the existing state once it's idle * * NOTE: arguably, we should also wait for all the other * RX channels to quiesce (how??) and then temporarily * disable RXCPPI_CTRL_REG ... but it seems that we can * rely on the controller restarting from state ram, with * only RXCPPI_BUFCNT state being bogus. BUFCNT will * correct itself after the next DMA transfer though. * * REVISIT does using rndis mode change that? */ cppi_reset_rx(cppi_ch->state_ram); /* next DMA request _should_ load cppi head ptr */ /* ... we don't "free" that list, only mutate it in place. */ cppi_dump_rx(5, cppi_ch, " (done abort)"); /* clean up previously pending bds */ cppi_bd_free(cppi_ch, cppi_ch->last_processed); cppi_ch->last_processed = NULL; while (queue) { struct cppi_descriptor *tmp = queue->next; cppi_bd_free(cppi_ch, queue); queue = tmp; } } channel->status = MUSB_DMA_STATUS_FREE; cppi_ch->buf_dma = 0; cppi_ch->offset = 0; cppi_ch->buf_len = 0; cppi_ch->maxpacket = 0; return 0; }
static bool cppi_rx_scan(struct cppi *cppi, unsigned ch) { struct cppi_channel *rx = &cppi->rx[ch]; struct cppi_rx_stateram __iomem *state = rx->state_ram; struct cppi_descriptor *bd; struct cppi_descriptor *last = rx->last_processed; bool completed = false; bool acked = false; int i; dma_addr_t safe2ack; void __iomem *regs = rx->hw_ep->regs; struct musb *musb = cppi->controller.musb; cppi_dump_rx(6, rx, "/K"); bd = last ? last->next : rx->head; if (!bd) return false; /* run through all completed BDs */ for (i = 0, safe2ack = musb_readl(&state->rx_complete, 0); (safe2ack || completed) && bd && i < NUM_RXCHAN_BD; i++, bd = bd->next) { u16 len; /* catch latest BD writes from CPPI */ rmb(); if (!completed && (bd->hw_options & CPPI_OWN_SET)) break; musb_dbg(musb, "C/RXBD %llx: nxt %08x buf %08x " "off.len %08x opt.len %08x (%d)", (unsigned long long)bd->dma, bd->hw_next, bd->hw_bufp, bd->hw_off_len, bd->hw_options, rx->channel.actual_len); /* actual packet received length */ if ((bd->hw_options & CPPI_SOP_SET) && !completed) len = bd->hw_off_len & CPPI_RECV_PKTLEN_MASK; else len = 0; if (bd->hw_options & CPPI_EOQ_MASK) completed = true; if (!completed && len < bd->buflen) { /* NOTE: when we get a short packet, RXCSR_H_REQPKT * must have been cleared, and no more DMA packets may * active be in the queue... TI docs didn't say, but * CPPI ignores those BDs even though OWN is still set. */ completed = true; musb_dbg(musb, "rx short %d/%d (%d)", len, bd->buflen, rx->channel.actual_len); } /* If we got here, we expect to ack at least one BD; meanwhile * CPPI may completing other BDs while we scan this list... * * RACE: we can notice OWN cleared before CPPI raises the * matching irq by writing that BD as the completion pointer. * In such cases, stop scanning and wait for the irq, avoiding * lost acks and states where BD ownership is unclear. */ if (bd->dma == safe2ack) { musb_writel(&state->rx_complete, 0, safe2ack); safe2ack = musb_readl(&state->rx_complete, 0); acked = true; if (bd->dma == safe2ack) safe2ack = 0; } rx->channel.actual_len += len; cppi_bd_free(rx, last); last = bd; /* stop scanning on end-of-segment */ if (bd->hw_next == 0) completed = true; } rx->last_processed = last; /* dma abort, lost ack, or ... */ if (!acked && last) { int csr; if (safe2ack == 0 || safe2ack == rx->last_processed->dma) musb_writel(&state->rx_complete, 0, safe2ack); if (safe2ack == 0) { cppi_bd_free(rx, last); rx->last_processed = NULL; /* if we land here on the host side, H_REQPKT will * be clear and we need to restart the queue... */ WARN_ON(rx->head); } musb_ep_select(cppi->mregs, rx->index + 1); csr = musb_readw(regs, MUSB_RXCSR); if (csr & MUSB_RXCSR_DMAENAB) { musb_dbg(musb, "list%d %p/%p, last %llx%s, csr %04x", rx->index, rx->head, rx->tail, rx->last_processed ? (unsigned long long) rx->last_processed->dma : 0, completed ? ", completed" : "", csr); cppi_dump_rxq(4, "/what?", rx); } } if (!completed) { int csr; rx->head = bd; /* REVISIT seems like "autoreq all but EOP" doesn't... * setting it here "should" be racey, but seems to work */ csr = musb_readw(rx->hw_ep->regs, MUSB_RXCSR); if (is_host_active(cppi->controller.musb) && bd && !(csr & MUSB_RXCSR_H_REQPKT)) { csr |= MUSB_RXCSR_H_REQPKT; musb_writew(regs, MUSB_RXCSR, MUSB_RXCSR_H_WZC_BITS | csr); csr = musb_readw(rx->hw_ep->regs, MUSB_RXCSR); } } else { rx->head = NULL; rx->tail = NULL; } cppi_dump_rx(6, rx, completed ? "/completed" : "/cleaned"); return completed; }
/* handle a standard GET_STATUS request * Context: caller holds controller lock */ static int service_tx_status_request( struct musb *musb, const struct usb_ctrlrequest *ctrlrequest) { void __iomem *mbase = musb->mregs; int handled = 1; u8 result[2], epnum = 0; const u8 recip = ctrlrequest->bRequestType & USB_RECIP_MASK; result[1] = 0; switch (recip) { case USB_RECIP_DEVICE: result[0] = musb->is_self_powered << USB_DEVICE_SELF_POWERED; result[0] |= musb->may_wakeup << USB_DEVICE_REMOTE_WAKEUP; #ifdef CONFIG_USB_MUSB_OTG if (musb->g.is_otg) { result[0] |= musb->g.b_hnp_enable << USB_DEVICE_B_HNP_ENABLE; result[0] |= musb->g.a_alt_hnp_support << USB_DEVICE_A_ALT_HNP_SUPPORT; result[0] |= musb->g.a_hnp_support << USB_DEVICE_A_HNP_SUPPORT; } #endif break; case USB_RECIP_INTERFACE: result[0] = 0; break; case USB_RECIP_ENDPOINT: { int is_in; struct musb_ep *ep; u16 tmp; void __iomem *regs; epnum = (u8) ctrlrequest->wIndex; if (!epnum) { result[0] = 0; break; } is_in = epnum & USB_DIR_IN; if (is_in) { epnum &= 0x0f; ep = &musb->endpoints[epnum].ep_in; } else { ep = &musb->endpoints[epnum].ep_out; } regs = musb->endpoints[epnum].regs; if (epnum >= MUSB_C_NUM_EPS || !ep->desc) { handled = -EINVAL; break; } musb_ep_select(mbase, epnum); if (is_in) tmp = musb_readw(regs, MUSB_TXCSR) & MUSB_TXCSR_P_SENDSTALL; else tmp = musb_readw(regs, MUSB_RXCSR) & MUSB_RXCSR_P_SENDSTALL; musb_ep_select(mbase, 0); result[0] = tmp ? 1 : 0; } break; default: /* class, vendor, etc ... delegate */ handled = 0; break; } /* fill up the fifo; caller updates csr0 */ if (handled > 0) { u16 len = le16_to_cpu(ctrlrequest->wLength); if (len > 2) len = 2; musb_write_fifo(&musb->endpoints[0], len, result); } return handled; }
static irqreturn_t dma_controller_irq(int irq, void *private_data) { struct musb_dma_controller *controller = private_data; struct musb *musb = controller->private_data; struct musb_dma_channel *musb_channel; struct dma_channel *channel; void __iomem *mbase = controller->base; irqreturn_t retval = IRQ_NONE; unsigned long flags; u8 bchannel; u8 int_hsdma; u32 addr; u16 csr; spin_lock_irqsave(&musb->lock, flags); int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR); if (!int_hsdma) goto done; for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) { if (int_hsdma & (1 << bchannel)) { musb_channel = (struct musb_dma_channel *) &(controller->channel[bchannel]); channel = &musb_channel->channel; csr = musb_readw(mbase, MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL)); if (csr & (1 << MUSB_HSDMA_BUSERROR_SHIFT)) { musb_channel->channel.status = MUSB_DMA_STATUS_BUS_ABORT; } else { u8 devctl; addr = musb_read_hsdma_addr(mbase, bchannel); channel->actual_len = addr - musb_channel->start_addr; DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n", channel, musb_channel->start_addr, addr, channel->actual_len, musb_channel->len, (channel->actual_len < musb_channel->len) ? "=> reconfig 0" : "=> complete"); devctl = musb_readb(mbase, MUSB_DEVCTL); channel->status = MUSB_DMA_STATUS_FREE; /* completed */ if ((devctl & MUSB_DEVCTL_HM) && (musb_channel->transmit) && ((channel->desired_mode == 0) || (channel->actual_len & (musb_channel->max_packet_sz - 1))) ) { /* Send out the packet */ musb_ep_select(mbase, musb_channel->epnum); musb_writew(mbase, MUSB_EP_OFFSET( musb_channel->epnum, MUSB_TXCSR), MUSB_TXCSR_TXPKTRDY); } else { musb_dma_completion( musb, musb_channel->epnum, musb_channel->transmit); } } } } #ifdef CONFIG_BLACKFIN /* Clear DMA interrup flags */ musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma); #endif retval = IRQ_HANDLED; done: spin_unlock_irqrestore(&musb->lock, flags); return retval; }
static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz, u8 rndis_mode, dma_addr_t dma_addr, u32 len) { struct tusb_omap_dma_ch *chdat = to_chdat(channel); struct tusb_omap_dma *tusb_dma = chdat->tusb_dma; struct musb *musb = chdat->musb; struct device *dev = musb->controller; struct musb_hw_ep *hw_ep = chdat->hw_ep; void __iomem *mbase = musb->mregs; void __iomem *ep_conf = hw_ep->conf; dma_addr_t fifo = hw_ep->fifo_sync; struct omap_dma_channel_params dma_params; u32 dma_remaining; int src_burst, dst_burst; u16 csr; int ch; s8 dmareq; s8 sync_dev; if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz)) return false; /* * HW issue #10: Async dma will eventually corrupt the XFR_SIZE * register which will cause missed DMA interrupt. We could try to * use a timer for the callback, but it is unsafe as the XFR_SIZE * register is corrupt, and we won't know if the DMA worked. */ if (dma_addr & 0x2) return false; /* * Because of HW issue #10, it seems like mixing sync DMA and async * PIO access can confuse the DMA. Make sure XFR_SIZE is reset before * using the channel for DMA. */ if (chdat->tx) dma_remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET); else dma_remaining = musb_readl(ep_conf, TUSB_EP_RX_OFFSET); dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining); if (dma_remaining) { dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n", chdat->tx ? "tx" : "rx", chdat->ch, dma_remaining); return false; } chdat->transfer_len = len & ~0x1f; if (len < packet_sz) chdat->transfer_packet_sz = chdat->transfer_len; else chdat->transfer_packet_sz = packet_sz; if (tusb_dma->multichannel) { ch = chdat->ch; dmareq = chdat->dmareq; sync_dev = chdat->sync_dev; } else { if (tusb_omap_use_shared_dmareq(chdat) != 0) { dev_dbg(musb->controller, "could not get dma for ep%i\n", chdat->epnum); return false; } if (tusb_dma->ch < 0) { /* REVISIT: This should get blocked earlier, happens * with MSC ErrorRecoveryTest */ WARN_ON(1); return false; } ch = tusb_dma->ch; dmareq = tusb_dma->dmareq; sync_dev = tusb_dma->sync_dev; omap_set_dma_callback(ch, tusb_omap_dma_cb, channel); } chdat->packet_sz = packet_sz; chdat->len = len; channel->actual_len = 0; chdat->dma_addr = dma_addr; channel->status = MUSB_DMA_STATUS_BUSY; /* Since we're recycling dma areas, we need to clean or invalidate */ if (chdat->tx) dma_map_single(dev, phys_to_virt(dma_addr), len, DMA_TO_DEVICE); else dma_map_single(dev, phys_to_virt(dma_addr), len, DMA_FROM_DEVICE); /* Use 16-bit transfer if dma_addr is not 32-bit aligned */ if ((dma_addr & 0x3) == 0) { dma_params.data_type = OMAP_DMA_DATA_TYPE_S32; dma_params.elem_count = 8; /* Elements in frame */ } else { dma_params.data_type = OMAP_DMA_DATA_TYPE_S16; dma_params.elem_count = 16; /* Elements in frame */ fifo = hw_ep->fifo_async; } dma_params.frame_count = chdat->transfer_len / 32; /* Burst sz frame */ dev_dbg(musb->controller, "ep%i %s dma ch%i dma: %08x len: %u(%u) packet_sz: %i(%i)\n", chdat->epnum, chdat->tx ? "tx" : "rx", ch, dma_addr, chdat->transfer_len, len, chdat->transfer_packet_sz, packet_sz); /* * Prepare omap DMA for transfer */ if (chdat->tx) { dma_params.src_amode = OMAP_DMA_AMODE_POST_INC; dma_params.src_start = (unsigned long)dma_addr; dma_params.src_ei = 0; dma_params.src_fi = 0; dma_params.dst_amode = OMAP_DMA_AMODE_DOUBLE_IDX; dma_params.dst_start = (unsigned long)fifo; dma_params.dst_ei = 1; dma_params.dst_fi = -31; /* Loop 32 byte window */ dma_params.trigger = sync_dev; dma_params.sync_mode = OMAP_DMA_SYNC_FRAME; dma_params.src_or_dst_synch = 0; /* Dest sync */ src_burst = OMAP_DMA_DATA_BURST_16; /* 16x32 read */ dst_burst = OMAP_DMA_DATA_BURST_8; /* 8x32 write */ } else { dma_params.src_amode = OMAP_DMA_AMODE_DOUBLE_IDX; dma_params.src_start = (unsigned long)fifo; dma_params.src_ei = 1; dma_params.src_fi = -31; /* Loop 32 byte window */ dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC; dma_params.dst_start = (unsigned long)dma_addr; dma_params.dst_ei = 0; dma_params.dst_fi = 0; dma_params.trigger = sync_dev; dma_params.sync_mode = OMAP_DMA_SYNC_FRAME; dma_params.src_or_dst_synch = 1; /* Source sync */ src_burst = OMAP_DMA_DATA_BURST_8; /* 8x32 read */ dst_burst = OMAP_DMA_DATA_BURST_16; /* 16x32 write */ } dev_dbg(musb->controller, "ep%i %s using %i-bit %s dma from 0x%08lx to 0x%08lx\n", chdat->epnum, chdat->tx ? "tx" : "rx", (dma_params.data_type == OMAP_DMA_DATA_TYPE_S32) ? 32 : 16, ((dma_addr & 0x3) == 0) ? "sync" : "async", dma_params.src_start, dma_params.dst_start); omap_set_dma_params(ch, &dma_params); omap_set_dma_src_burst_mode(ch, src_burst); omap_set_dma_dest_burst_mode(ch, dst_burst); omap_set_dma_write_mode(ch, OMAP_DMA_WRITE_LAST_NON_POSTED); /* * Prepare MUSB for DMA transfer */ if (chdat->tx) { musb_ep_select(mbase, chdat->epnum); csr = musb_readw(hw_ep->regs, MUSB_TXCSR); csr |= (MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE); csr &= ~MUSB_TXCSR_P_UNDERRUN; musb_writew(hw_ep->regs, MUSB_TXCSR, csr); } else { musb_ep_select(mbase, chdat->epnum); csr = musb_readw(hw_ep->regs, MUSB_RXCSR); csr |= MUSB_RXCSR_DMAENAB; csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAMODE); musb_writew(hw_ep->regs, MUSB_RXCSR, csr | MUSB_RXCSR_P_WZC_BITS); } /* * Start DMA transfer */ omap_start_dma(ch); if (chdat->tx) { /* Send transfer_packet_sz packets at a time */ musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, chdat->transfer_packet_sz); musb_writel(ep_conf, TUSB_EP_TX_OFFSET, TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len)); } else { /* Receive transfer_packet_sz packets at a time */ musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, chdat->transfer_packet_sz << 16); musb_writel(ep_conf, TUSB_EP_RX_OFFSET, TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len)); } return true; }
/* * See also musb_dma_completion in plat_uds.c and musb_g_[tx|rx]() in * musb_gadget.c. */ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data) { struct dma_channel *channel = (struct dma_channel *)data; struct tusb_omap_dma_ch *chdat = to_chdat(channel); struct tusb_omap_dma *tusb_dma = chdat->tusb_dma; struct musb *musb = chdat->musb; struct device *dev = musb->controller; struct musb_hw_ep *hw_ep = chdat->hw_ep; void __iomem *ep_conf = hw_ep->conf; void __iomem *mbase = musb->mregs; unsigned long remaining, flags, pio; int ch; spin_lock_irqsave(&musb->lock, flags); if (tusb_dma->multichannel) ch = chdat->ch; else ch = tusb_dma->ch; if (ch_status != OMAP_DMA_BLOCK_IRQ) printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status); dev_dbg(musb->controller, "ep%i %s dma callback ch: %i status: %x\n", chdat->epnum, chdat->tx ? "tx" : "rx", ch, ch_status); if (chdat->tx) remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET); else remaining = musb_readl(ep_conf, TUSB_EP_RX_OFFSET); remaining = TUSB_EP_CONFIG_XFR_SIZE(remaining); /* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */ if (unlikely(remaining > chdat->transfer_len)) { dev_dbg(musb->controller, "Corrupt %s dma ch%i XFR_SIZE: 0x%08lx\n", chdat->tx ? "tx" : "rx", chdat->ch, remaining); remaining = 0; } channel->actual_len = chdat->transfer_len - remaining; pio = chdat->len - channel->actual_len; dev_dbg(musb->controller, "DMA remaining %lu/%u\n", remaining, chdat->transfer_len); /* Transfer remaining 1 - 31 bytes */ if (pio > 0 && pio < 32) { u8 *buf; dev_dbg(musb->controller, "Using PIO for remaining %lu bytes\n", pio); buf = phys_to_virt((u32)chdat->dma_addr) + chdat->transfer_len; if (chdat->tx) { dma_unmap_single(dev, chdat->dma_addr, chdat->transfer_len, DMA_TO_DEVICE); musb_write_fifo(hw_ep, pio, buf); } else { dma_unmap_single(dev, chdat->dma_addr, chdat->transfer_len, DMA_FROM_DEVICE); musb_read_fifo(hw_ep, pio, buf); } channel->actual_len += pio; } if (!tusb_dma->multichannel) tusb_omap_free_shared_dmareq(chdat); channel->status = MUSB_DMA_STATUS_FREE; /* Handle only RX callbacks here. TX callbacks must be handled based * on the TUSB DMA status interrupt. * REVISIT: Use both TUSB DMA status interrupt and OMAP DMA callback * interrupt for RX and TX. */ if (!chdat->tx) musb_dma_completion(musb, chdat->epnum, chdat->tx); /* We must terminate short tx transfers manually by setting TXPKTRDY. * REVISIT: This same problem may occur with other MUSB dma as well. * Easy to test with g_ether by pinging the MUSB board with ping -s54. */ if ((chdat->transfer_len < chdat->packet_sz) || (chdat->transfer_len % chdat->packet_sz != 0)) { u16 csr; if (chdat->tx) { dev_dbg(musb->controller, "terminating short tx packet\n"); musb_ep_select(mbase, chdat->epnum); csr = musb_readw(hw_ep->regs, MUSB_TXCSR); csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_P_WZC_BITS; musb_writew(hw_ep->regs, MUSB_TXCSR, csr); } } spin_unlock_irqrestore(&musb->lock, flags); }