コード例 #1
0
ファイル: s3c_udc_otg_xfer_dma.c プロジェクト: Apaisal/u-boot
static void complete_rx(struct s3c_udc *dev, u8 ep_num)
{
	struct s3c_ep *ep = &dev->ep[ep_num];
	struct s3c_request *req = NULL;
	u32 ep_tsr = 0, xfer_size = 0, is_short = 0;
	u32 *p = the_controller->dma_buf[ep_index(ep)+1];

	if (list_empty(&ep->queue)) {
		DEBUG_OUT_EP("%s: RX DMA done : NULL REQ on OUT EP-%d\n",
					__func__, ep_num);
		return;

	}

	req = list_entry(ep->queue.next, struct s3c_request, queue);
	ep_tsr = readl(&reg->out_endp[ep_num].doeptsiz);

	if (ep_num == EP0_CON)
		xfer_size = (ep_tsr & DOEPT_SIZ_XFER_SIZE_MAX_EP0);
	else
		xfer_size = (ep_tsr & DOEPT_SIZ_XFER_SIZE_MAX_EP);

	xfer_size = ep->len - xfer_size;

	invalidate_dcache_range((unsigned long) p,
				(unsigned long) p + DMA_BUFFER_SIZE);

	memcpy(ep->dma_buf, p, ep->len);

	req->req.actual += min(xfer_size, req->req.length - req->req.actual);
	is_short = (xfer_size < ep->ep.maxpacket);

	DEBUG_OUT_EP("%s: RX DMA done : ep = %d, rx bytes = %d/%d, "
		     "is_short = %d, DOEPTSIZ = 0x%x, remained bytes = %d\n",
			__func__, ep_num, req->req.actual, req->req.length,
			is_short, ep_tsr, xfer_size);

	if (is_short || req->req.actual == req->req.length) {
		if (ep_num == EP0_CON && dev->ep0state == DATA_STATE_RECV) {
			DEBUG_OUT_EP("	=> Send ZLP\n");
			s3c_udc_ep0_zlp(dev);
			/* packet will be completed in complete_tx() */
			dev->ep0state = WAIT_FOR_IN_COMPLETE;
		} else {
			done(ep, req, 0);

			if (!list_empty(&ep->queue)) {
				req = list_entry(ep->queue.next,
					struct s3c_request, queue);
				DEBUG_OUT_EP("%s: Next Rx request start...\n",
					 __func__);
				setdma_rx(ep, req);
			}
		}
	} else
コード例 #2
0
static void complete_rx(struct s3c_udc *dev, u8 ep_num)
{
	struct s3c_ep *ep = &dev->ep[ep_num];
	struct s3c_request *req = NULL;
	u32 ep_tsr = 0, xfer_size = 0, xfer_length, is_short = 0;

	if (list_empty(&ep->queue)) {
		DEBUG_OUT_EP("%s: RX DMA done : NULL REQ on OUT EP-%d\n",
					__func__, ep_num);
		return;

	}

	req = list_entry(ep->queue.next, struct s3c_request, queue);

	ep_tsr = readl(S3C_UDC_OTG_DOEPTSIZ(ep_num));

	if (ep_num == EP0_CON)
		xfer_size = (ep_tsr & 0x7f);

	else
		xfer_size = (ep_tsr & 0x7fff);
	
	dma_cache_maint(req->req.buf, req->req.length, DMA_FROM_DEVICE);
	xfer_length = req->req.length - xfer_size;
	req->req.actual += min(xfer_length, req->req.length - req->req.actual);
	is_short = (xfer_length < ep->ep.maxpacket);

	DEBUG_OUT_EP("%s: RX DMA done : ep = %d, rx bytes = %d/%d, "
		     "is_short = %d, DOEPTSIZ = 0x%x, remained bytes = %d\n",
			__func__, ep_num, req->req.actual, req->req.length,
			is_short, ep_tsr, xfer_size);

	if (is_short || req->req.actual == xfer_length) {
		if(ep_num == EP0_CON && dev->ep0state == DATA_STATE_RECV) {
			DEBUG_OUT_EP("	=> Send ZLP\n");
			dev->ep0state = WAIT_FOR_SETUP;
			s3c_udc_ep0_zlp();

		} else {
			done(ep, req, 0);

			if(!list_empty(&ep->queue)) {
				req = list_entry(ep->queue.next, struct s3c_request, queue);
				DEBUG_OUT_EP("%s: Next Rx request start...\n", __func__);
				if (ep_num == EP0_CON && dev->ep0state == WAIT_FOR_SETUP)
					setdma_rx(ep, req, 1);
				else
					setdma_rx(ep, req, 0);
			}
		}
	}
コード例 #3
0
static void s3c_out_epn(struct s3c_udc *dev, u32 ep_idx)
{
	struct s3c_ep *ep = &dev->ep[ep_idx];
	struct s3c_request *req;

	if (unlikely(!(ep->desc))) {
		/* Throw packet away.. */
		printk("%s: No descriptor?!?\n", __FUNCTION__);
		return;
	}

	if (list_empty(&ep->queue))
		req = 0;
	else
		req = list_entry(ep->queue.next,
				struct s3c_request, queue);

	if (unlikely(!req)) {
		DEBUG_OUT_EP("%s: NULL REQ on OUT EP-%d\n", __FUNCTION__, ep_idx);
		return;

	} else {
		read_fifo(ep, req);
	}

}
コード例 #4
0
static int setdma_rx(struct s3c_ep *ep, struct s3c_request *req)
{
	u32 *buf, ctrl;
	u32 length, pktcnt;
	u32 ep_num = ep_index(ep);

	buf = req->req.buf + req->req.actual;
	prefetchw(buf);

	length = req->req.length - req->req.actual;
	dma_cache_maint(buf, length, DMA_FROM_DEVICE);

	if(length == 0)
		pktcnt = 1;
	else
		pktcnt = (length - 1)/(ep->ep.maxpacket) + 1;

	ctrl =  readl(S3C_UDC_OTG_DOEPCTL(ep_num));

	writel(virt_to_phys(buf), S3C_UDC_OTG_DOEPDMA(ep_num));
	writel((pktcnt<<19)|(length<<0), S3C_UDC_OTG_DOEPTSIZ(ep_num));
	writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, S3C_UDC_OTG_DOEPCTL(ep_num));

	DEBUG_OUT_EP("%s: EP%d RX DMA start : DOEPDMA = 0x%x, DOEPTSIZ = 0x%x, DOEPCTL = 0x%x\n"
			"\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n",
			__func__, ep_num,
			readl(S3C_UDC_OTG_DOEPDMA(ep_num)),
			readl(S3C_UDC_OTG_DOEPTSIZ(ep_num)),
			readl(S3C_UDC_OTG_DOEPCTL(ep_num)),
			buf, pktcnt, length);
	return 0;

}
コード例 #5
0
static int setdma_rx(struct s3c_ep *ep, struct s3c_request *req)
{
	u32 *buf, ctrl;
	u32 length, pktcnt;
	u32 ep_num = ep_index(ep);
	struct s3c_udc *udc = ep->dev;
	struct device *dev = &udc->dev->dev;

	aligned_map_buf(req, ep_is_in(ep));
	buf = req->req.buf + req->req.actual;
	prefetchw(buf);

	length = req->req.length - req->req.actual;

	req->req.dma = dma_map_single(dev, buf,
				length, DMA_FROM_DEVICE);
	req->mapped = 1;

	if (length == 0)
		pktcnt = 1;
	else
		pktcnt = (length - 1)/(ep->ep.maxpacket) + 1;

	ctrl =  __raw_readl(udc->regs + S3C_UDC_OTG_DOEPCTL(ep_num));

	__raw_writel(virt_to_phys(buf),
		udc->regs + S3C_UDC_OTG_DOEPDMA(ep_num));
	__raw_writel((pktcnt<<19) | (length<<0),
		udc->regs + S3C_UDC_OTG_DOEPTSIZ(ep_num));
	__raw_writel(DEPCTL_EPENA | DEPCTL_CNAK | ctrl,
		udc->regs + S3C_UDC_OTG_DOEPCTL(ep_num));

	DEBUG_OUT_EP("%s: EP%d RX DMA start : DOEPDMA = 0x%x,"
			"DOEPTSIZ = 0x%x, DOEPCTL = 0x%x\n"
			"\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n",
			__func__, ep_num,
			__raw_readl(udc->regs + S3C_UDC_OTG_DOEPDMA(ep_num)),
			__raw_readl(udc->regs + S3C_UDC_OTG_DOEPTSIZ(ep_num)),
			__raw_readl(udc->regs + S3C_UDC_OTG_DOEPCTL(ep_num)),
			buf, pktcnt, length);
	return 0;
}
コード例 #6
0
ファイル: s3c_udc_otg_xfer_dma.c プロジェクト: Apaisal/u-boot
static int setdma_rx(struct s3c_ep *ep, struct s3c_request *req)
{
	u32 *buf, ctrl;
	u32 length, pktcnt;
	u32 ep_num = ep_index(ep);

	buf = req->req.buf + req->req.actual;

	length = min(req->req.length - req->req.actual, (int)ep->ep.maxpacket);

	ep->len = length;
	ep->dma_buf = buf;

	invalidate_dcache_range((unsigned long) ep->dev->dma_buf[ep_num],
				(unsigned long) ep->dev->dma_buf[ep_num]
				+ DMA_BUFFER_SIZE);

	if (length == 0)
		pktcnt = 1;
	else
		pktcnt = (length - 1)/(ep->ep.maxpacket) + 1;

	pktcnt = 1;
	ctrl =  readl(&reg->out_endp[ep_num].doepctl);

	writel(the_controller->dma_addr[ep_index(ep)+1],
	       &reg->out_endp[ep_num].doepdma);
	writel(DOEPT_SIZ_PKT_CNT(pktcnt) | DOEPT_SIZ_XFER_SIZE(length),
	       &reg->out_endp[ep_num].doeptsiz);
	writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, &reg->out_endp[ep_num].doepctl);

	DEBUG_OUT_EP("%s: EP%d RX DMA start : DOEPDMA = 0x%x,"
		     "DOEPTSIZ = 0x%x, DOEPCTL = 0x%x\n"
		     "\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n",
		     __func__, ep_num,
		     readl(&reg->out_endp[ep_num].doepdma),
		     readl(&reg->out_endp[ep_num].doeptsiz),
		     readl(&reg->out_endp[ep_num].doepctl),
		     buf, pktcnt, length);
	return 0;

}
コード例 #7
0
/** Read to request from FIFO (max read == bytes in fifo)
 *  Return:  0 = still running, 1 = completed, negative = errno
 */
static int read_fifo(struct s3c_ep *ep, struct s3c_request *req)
{
	u32 csr, gintmsk;
	u32 *buf;
	u32 bufferspace, count, count_bytes, is_short = 0;
	u32 fifo = ep->fifo;

	csr = readl(S3C_UDC_OTG_GRXSTSP);
	count_bytes = (csr & 0x7ff0)>>4;

	gintmsk = readl(S3C_UDC_OTG_GINTMSK);

	if(!count_bytes) {
		DEBUG_OUT_EP("%s: count_bytes %d bytes\n", __FUNCTION__, count_bytes);

		/* Unmask USB OTG 2.0 interrupt source : INT_RX_FIFO_NOT_EMPTY */
		writel(gintmsk | INT_RX_FIFO_NOT_EMPTY, S3C_UDC_OTG_GINTMSK);
		return 0;
	}

	buf = req->req.buf + req->req.actual;
	prefetchw(buf);
	bufferspace = req->req.length - req->req.actual;

	count = count_bytes / 4;
	if (count_bytes%4)
		count = count + 1;

	req->req.actual += min(count_bytes, bufferspace);

	is_short = (count_bytes < ep->ep.maxpacket);
	DEBUG_OUT_EP("%s: read %s, %d bytes%s req %p %d/%d GRXSTSP:0x%x\n",
		__FUNCTION__,
		ep->ep.name, count_bytes,
		is_short ? "/S" : "", req, req->req.actual, req->req.length, csr);

	while (likely(count-- != 0)) {
		u32 byte = (u32) readl(fifo);

		if (unlikely(bufferspace == 0)) {
			/* this happens when the driver's buffer
		 	* is smaller than what the host sent.
		 	* discard the extra data.
		 	*/
			if (req->req.status != -EOVERFLOW)
				printk("%s overflow %d\n", ep->ep.name, count);
			req->req.status = -EOVERFLOW;
		} else {
			*buf++ = byte;
			bufferspace-=4;
		}
 	 }

	/* Unmask USB OTG 2.0 interrupt source : INT_RX_FIFO_NOT_EMPTY */
	writel(gintmsk | INT_RX_FIFO_NOT_EMPTY, S3C_UDC_OTG_GINTMSK);

	/* completion */
	if (is_short || req->req.actual == req->req.length) {
		done(ep, req, 0);
		return 1;
	}

	/* finished that packet.  the next one may be waiting... */
	return 0;
}