Пример #1
0
/*
 * Load an endpoint's FIFO
 */
void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
{
    void __iomem *fifo;
    if(mtk_musb->is_host)
	    fifo = hw_ep->fifo;
    else
	    fifo = mtk_musb->mregs + MUSB_FIFO_OFFSET(hw_ep->ep_in.current_epnum);

	prefetch((u8 *)src);

	DBG(4, "%cX ep%d fifo %p count %d buf %p\n",
			'T', hw_ep->epnum, fifo, len, src);

	/* we can't assume unaligned reads work */
	if (likely((0x01 & (unsigned long) src) == 0)) {
		u16	index = 0;

		/* best case is 32bit-aligned source address */
		if ((0x02 & (unsigned long) src) == 0) {
			if (len >= 4) {
				writesl(fifo, src + index, len >> 2);
				index += len & ~0x03;
			}
			if (len & 0x02) {
				dumpTime(funcWritew, 0);
				musb_writew(fifo, 0, *(u16 *)&src[index]);
				index += 2;
			}
		} else {
Пример #2
0
static bool ux500_configure_channel(struct dma_channel *channel,
                                    u16 packet_sz, u8 mode,
                                    dma_addr_t dma_addr, u32 len)
{
    struct ux500_dma_channel *ux500_channel = channel->private_data;
    struct musb_hw_ep *hw_ep = ux500_channel->hw_ep;
    struct dma_chan *dma_chan = ux500_channel->dma_chan;
    struct dma_async_tx_descriptor *dma_desc;
    enum dma_transfer_direction direction;
    struct scatterlist sg;
    struct dma_slave_config slave_conf;
    enum dma_slave_buswidth addr_width;
    dma_addr_t usb_fifo_addr = (MUSB_FIFO_OFFSET(hw_ep->epnum) +
                                ux500_channel->controller->phy_base);
    struct musb *musb = ux500_channel->controller->private_data;

    dev_dbg(musb->controller,
            "packet_sz=%d, mode=%d, dma_addr=0x%llu, len=%d is_tx=%d\n",
            packet_sz, mode, (unsigned long long) dma_addr,
            len, ux500_channel->is_tx);

    ux500_channel->cur_len = len;

    sg_init_table(&sg, 1);
    sg_set_page(&sg, pfn_to_page(PFN_DOWN(dma_addr)), len,
                offset_in_page(dma_addr));
    sg_dma_address(&sg) = dma_addr;
    sg_dma_len(&sg) = len;

    direction = ux500_channel->is_tx ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
    addr_width = (len & 0x3) ? DMA_SLAVE_BUSWIDTH_1_BYTE :
                 DMA_SLAVE_BUSWIDTH_4_BYTES;

    slave_conf.direction = direction;
    slave_conf.src_addr = usb_fifo_addr;
    slave_conf.src_addr_width = addr_width;
    slave_conf.src_maxburst = 16;
    slave_conf.dst_addr = usb_fifo_addr;
    slave_conf.dst_addr_width = addr_width;
    slave_conf.dst_maxburst = 16;
    slave_conf.device_fc = false;

    dma_chan->device->device_control(dma_chan, DMA_SLAVE_CONFIG,
                                     (unsigned long) &slave_conf);

    dma_desc = dmaengine_prep_slave_sg(dma_chan, &sg, 1, direction,
                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
    if (!dma_desc)
        return false;

    dma_desc->callback = ux500_dma_callback;
    dma_desc->callback_param = channel;
    ux500_channel->cookie = dma_desc->tx_submit(dma_desc);

    dma_async_issue_pending(dma_chan);

    return true;
}