static inline void s3c_ep0_complete_out(void)
{
	u32 ep_ctrl;

	DEBUG_EP0("%s:EP0 ZLP DIEPCTL0 = 0x%x\n",
		__func__, readl(&reg->in_endp[EP0_CON].diepctl));
	DEBUG_EP0("%s:EP0 ZLP DOEPCTL0 = 0x%x\n",
		__func__, readl(&reg->out_endp[EP0_CON].doepctl));

	DEBUG_IN_EP("%s : Prepare Complete Out packet.\n", __func__);

	writel((1 << 19) | sizeof(struct usb_ctrlrequest),
	       &reg->out_endp[EP0_CON].doeptsiz);
	writel(usb_ctrl_dma_addr, &reg->out_endp[EP0_CON].doepdma);

	ep_ctrl = readl(&reg->out_endp[EP0_CON].doepctl);
	writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK,
	       &reg->out_endp[EP0_CON].doepctl);

	DEBUG_EP0("%s:EP0 ZLP DIEPCTL0 = 0x%x\n",
		__func__, readl(&reg->in_endp[EP0_CON].diepctl));
	DEBUG_EP0("%s:EP0 ZLP DOEPCTL0 = 0x%x\n",
		__func__, readl(&reg->out_endp[EP0_CON].doepctl));

}
Exemple #2
0
static int setdma_tx(struct s3c_ep *ep, struct s3c_request *req)
{
	u32 *buf, ctrl = 0;
	u32 length, pktcnt;
	u32 ep_num = ep_index(ep);
	struct device *dev = &the_controller->dev->dev;

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

	if (ep_num == EP0_CON)
		length = min(length, (u32)ep_maxpacket(ep));

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

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

#ifdef DED_TX_FIFO
	/* Flush the endpoint's Tx FIFO */
	writel(ep_num<<6, S3C_UDC_OTG_GRSTCTL);
	writel((ep_num<<6)|0x20, S3C_UDC_OTG_GRSTCTL);
	while (readl(S3C_UDC_OTG_GRSTCTL) & 0x20)
		;

	/* Write the FIFO number to be used for this endpoint */
	ctrl = readl(S3C_UDC_OTG_DIEPCTL(ep_num));
	ctrl &= ~DEPCTL_TXFNUM_MASK;;
	ctrl |= (ep_num << DEPCTL_TXFNUM_BIT);
	writel(ctrl , S3C_UDC_OTG_DIEPCTL(ep_num));
#endif

	writel(virt_to_phys(buf), S3C_UDC_OTG_DIEPDMA(ep_num));
	writel((pktcnt<<19)|(length<<0), S3C_UDC_OTG_DIEPTSIZ(ep_num));
	ctrl = readl(S3C_UDC_OTG_DIEPCTL(ep_num));
	writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, S3C_UDC_OTG_DIEPCTL(ep_num));

#ifndef DED_TX_FIFO
	ctrl = readl(S3C_UDC_OTG_DIEPCTL(EP0_CON));
	ctrl = (ctrl&~(EP_MASK<<DEPCTL_NEXT_EP_BIT))|(ep_num<<DEPCTL_NEXT_EP_BIT);
	writel(ctrl, S3C_UDC_OTG_DIEPCTL(EP0_CON));
#endif

	DEBUG_IN_EP("%s:EP%d TX DMA start : DIEPDMA0 = 0x%x, DIEPTSIZ0 = 0x%x, DIEPCTL0 = 0x%x\n"
			"\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n",
			__func__, ep_num,
			readl(S3C_UDC_OTG_DIEPDMA(ep_num)),
			readl(S3C_UDC_OTG_DIEPTSIZ(ep_num)),
			readl(S3C_UDC_OTG_DIEPCTL(ep_num)),
			buf, pktcnt, length);

	return length;
}
//set ep_num's DIEPCTLn.nextep 4 bits next_ep for EP_IN
static void s3c_set_next_ep(u8 ep_num, u8 next_ep)
{
	u32 ctrl;

	ctrl = readl(S3C_UDC_OTG_DIEPCTL0+DEP_OFFSET*ep_num);
	//DIEPCTLn.nextep 4bits
	ctrl &= ~(0xf<<DIEPCTL_NEXT_EP_BIT);	
	writel(next_ep<<DIEPCTL_NEXT_EP_BIT |ctrl, S3C_UDC_OTG_DIEPCTL0+DEP_OFFSET*ep_num);
	
	DEBUG_IN_EP("[%s] : set EP[%d].nextep => EP[%d]\n", __FUNCTION__, ep_num, next_ep);
}
Exemple #4
0
static inline void s3c_udc_pre_setup(void)
{
	u32 ep_ctrl;

	DEBUG_IN_EP("%s : Prepare Setup packets.\n", __func__);

	writel((1 << 19)|sizeof(struct usb_ctrlrequest), S3C_UDC_OTG_DOEPTSIZ(EP0_CON));
	writel(virt_to_phys(&usb_ctrl), S3C_UDC_OTG_DOEPDMA(EP0_CON));

	ep_ctrl = readl(S3C_UDC_OTG_DOEPCTL(EP0_CON));
	writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, S3C_UDC_OTG_DOEPCTL(EP0_CON));
}
static inline void s3c_udc_pre_setup(struct s3c_udc *dev)
{
	u32 ep_ctrl;

	DEBUG_IN_EP("%s : Prepare Setup packets.\n", __func__);

	__raw_writel((3<<29) | (1<<19) | sizeof(struct usb_ctrlrequest),
		dev->regs + S3C_UDC_OTG_DOEPTSIZ(EP0_CON));
	__raw_writel(dev->usb_ctrl_dma, dev->regs + S3C_UDC_OTG_DOEPDMA(EP0_CON));

	ep_ctrl = __raw_readl(dev->regs + S3C_UDC_OTG_DOEPCTL(EP0_CON));
	__raw_writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK,
		dev->regs + S3C_UDC_OTG_DOEPCTL(EP0_CON));
}
Exemple #6
0
static int setdma_tx(struct s3c_ep *ep, struct s3c_request *req)
{
	u32 *buf, ctrl = 0;
	u32 length, pktcnt;
	u32 ep_num = ep_index(ep);

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

	if (ep_num == EP0_CON) {
		length = min(length, (u32)ep_maxpacket(ep));
	}

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

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

#ifdef DED_TX_FIFO
	/* Write the FIFO number to be used for this endpoint */
	ctrl = readl(S3C_UDC_OTG_DIEPCTL(ep_num));
	ctrl &= ~DEPCTL_TXFNUM_MASK;;
	ctrl |= (ep_num << DEPCTL_TXFNUM_BIT);
	writel(ctrl , S3C_UDC_OTG_DIEPCTL(ep_num));
#endif

	writel(virt_to_phys(buf), S3C_UDC_OTG_DIEPDMA(ep_num));
	writel((pktcnt<<19)|(length<<0), S3C_UDC_OTG_DIEPTSIZ(ep_num));
	ctrl = readl(S3C_UDC_OTG_DIEPCTL(ep_num));
	writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, S3C_UDC_OTG_DIEPCTL(ep_num));

	ctrl = readl(S3C_UDC_OTG_DIEPCTL(EP0_CON));
	ctrl = (ctrl&~(EP_MASK<<DEPCTL_NEXT_EP_BIT))|(ep_num<<DEPCTL_NEXT_EP_BIT);
	writel(ctrl, S3C_UDC_OTG_DIEPCTL(EP0_CON));

	DEBUG_IN_EP("%s:EP%d TX DMA start : DIEPDMA0 = 0x%x, DIEPTSIZ0 = 0x%x, DIEPCTL0 = 0x%x\n"
			"\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n",
			__func__, ep_num,
			readl(S3C_UDC_OTG_DIEPDMA(ep_num)),
			readl(S3C_UDC_OTG_DIEPTSIZ(ep_num)),
			readl(S3C_UDC_OTG_DIEPCTL(ep_num)),
			buf, pktcnt, length);

	return length;
}
/** Write request to FIFO (max write == maxp size)
 *  Return:  0 = still running, 1 = completed, negative = errno
 */
static int write_fifo(struct s3c_ep *ep, struct s3c_request *req)
{
	u32 max, gintmsk;
	unsigned count;
	int is_last = 0, is_short = 0;

	gintmsk = readl(S3C_UDC_OTG_GINTMSK);

	max = le16_to_cpu(ep->desc->wMaxPacketSize);
	count = write_packet(ep, req, max);

	/* last packet is usually short (or a zlp) */
	if (unlikely(count != max))
		is_last = is_short = 1;
	else {
		if (likely(req->req.length != req->req.actual)
		    || req->req.zero)
			is_last = 0;
		else
			is_last = 1;
		/* interrupt/iso maxpacket may not fill the fifo */
		is_short = unlikely(max < ep_maxpacket(ep));
	}

	DEBUG_IN_EP("%s: wrote %s %d bytes%s%s req %p %d/%d\n",
			__FUNCTION__,
      			ep->ep.name, count,
     	 		is_last ? "/L" : "", is_short ? "/S" : "",
      			req, req->req.actual, req->req.length);

	/* requests complete when all IN data is in the FIFO */
	if (is_last) {
		if(!ep_index(ep)){
			printk("%s: --> Error EP0 must not come here!\n",
				__FUNCTION__);
			BUG();
		}
		writel(gintmsk&(~INT_NP_TX_FIFO_EMPTY), S3C_UDC_OTG_GINTMSK);
		done(ep, req, 0);
		return 1;
	}

	/* Unmask USB OTG 2.0 interrupt source : INT_NP_TX_FIFO_EMPTY */
	writel(gintmsk | INT_NP_TX_FIFO_EMPTY, S3C_UDC_OTG_GINTMSK);
	return 0;
}
/**
 * s3c_in_epn - handle IN interrupt
 */
static void s3c_in_epn(struct s3c_udc *dev, u32 ep_idx)
{
	struct s3c_ep *ep = &dev->ep[ep_idx];
	struct s3c_request *req;

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

	if (unlikely(!req)) {
		DEBUG_IN_EP("%s: NULL REQ on IN EP-%d\n", __FUNCTION__, ep_idx);
		return;
	} else {
		write_fifo(ep, req);
	}

}
static inline void s3c_udc_pre_setup(void)
{
	u32 ep_ctrl;

	DEBUG_IN_EP("%s : Prepare Setup packets.\n", __func__);

	writel((1 << 19) | sizeof(struct usb_ctrlrequest),
	       &reg->out_endp[EP0_CON].doeptsiz);
	writel(usb_ctrl_dma_addr, &reg->out_endp[EP0_CON].doepdma);

	ep_ctrl = readl(&reg->out_endp[EP0_CON].doepctl);
	writel(ep_ctrl|DEPCTL_EPENA, &reg->out_endp[EP0_CON].doepctl);

	DEBUG_EP0("%s:EP0 ZLP DIEPCTL0 = 0x%x\n",
		__func__, readl(&reg->in_endp[EP0_CON].diepctl));
	DEBUG_EP0("%s:EP0 ZLP DOEPCTL0 = 0x%x\n",
		__func__, readl(&reg->out_endp[EP0_CON].doepctl));

}
/* Inline code */
static __inline__ int write_packet(struct s3c_ep *ep,
				   struct s3c_request *req, int max)
{
	u32 *buf;
	int length, count;
	u32 fifo = ep->fifo, in_ctrl;

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

	length = req->req.length - req->req.actual;
	length = min(length, max);
	req->req.actual += length;

	DEBUG("%s: Write %d (max %d), fifo=0x%x\n",
		__FUNCTION__, length, max, fifo);

	if(ep_index(ep) == EP0_CON) {
		writel((1<<19)|(length<<0), (u32) S3C_UDC_OTG_DIEPTSIZ0);

		in_ctrl =  readl(S3C_UDC_OTG_DIEPCTL0);
		writel(DEPCTL_EPENA|DEPCTL_CNAK|(EP2_IN<<11)| in_ctrl, (u32) S3C_UDC_OTG_DIEPCTL0);

		DEBUG_EP0("%s:(DIEPTSIZ0):0x%x, (DIEPCTL0):0x%x, (GNPTXSTS):0x%x\n", __FUNCTION__,
			readl(S3C_UDC_OTG_DIEPTSIZ0),readl(S3C_UDC_OTG_DIEPCTL0),
			readl(S3C_UDC_OTG_GNPTXSTS));

		udelay(30);

	} else if ((ep_index(ep) == EP2_IN)) {
		writel((1<<19)|(length<<0), S3C_UDC_OTG_DIEPTSIZ2);

		in_ctrl =  readl(S3C_UDC_OTG_DIEPCTL2);
		writel(DEPCTL_EPENA|DEPCTL_CNAK|(EP2_IN<<11)| in_ctrl, (u32) S3C_UDC_OTG_DIEPCTL2);

		DEBUG_IN_EP("%s:(DIEPTSIZ2):0x%x, (DIEPCTL2):0x%x, (GNPTXSTS):0x%x\n", __FUNCTION__,
			readl(S3C_UDC_OTG_DIEPTSIZ2),readl(S3C_UDC_OTG_DIEPCTL2),
			readl(S3C_UDC_OTG_GNPTXSTS));

		udelay(30);

	} else if ((ep_index(ep) == EP3_IN)) {

		if (set_interface_first == 1) {
			DEBUG_IN_EP("%s: first packet write skipped after set_interface\n", __FUNCTION__);
			set_interface_first = 0;
			return length;
		}

		writel((1<<19)|(length<<0), S3C_UDC_OTG_DIEPTSIZ3);

		in_ctrl =  readl(S3C_UDC_OTG_DIEPCTL3);
		writel(DEPCTL_EPENA|DEPCTL_CNAK|(EP2_IN<<11)| in_ctrl, (u32) S3C_UDC_OTG_DIEPCTL3);

		DEBUG_IN_EP("%s:(DIEPTSIZ3):0x%x, (DIEPCTL3):0x%x, (GNPTXSTS):0x%x\n", __FUNCTION__,
			readl(S3C_UDC_OTG_DIEPTSIZ3),readl(S3C_UDC_OTG_DIEPCTL3),
			readl(S3C_UDC_OTG_GNPTXSTS));

		udelay(30);

	} else {
		printk("%s: --> Error Unused Endpoint!!\n",
			__FUNCTION__);
		BUG();
	}

	for (count = 0; count < length; count += 4)
	  	writel(*buf++, fifo);

	return length;
}
static int setdma_tx(struct s3c_ep *ep, struct s3c_request *req)
{
	u32 *buf, ctrl = 0;
	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;
	prefetch(buf);
	length = req->req.length - req->req.actual;

	if (ep_num == EP0_CON)
		length = min_t(u32, length, (u32)ep_maxpacket(ep));

	req->req.actual += length;

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

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

#ifdef DED_TX_FIFO
	/* Write the FIFO number to be used for this endpoint */
	ctrl = __raw_readl(udc->regs + S3C_UDC_OTG_DIEPCTL(ep_num));
	ctrl &= ~DEPCTL_TXFNUM_MASK;
	ctrl |= (ep_num << DEPCTL_TXFNUM_BIT);
	__raw_writel(ctrl , udc->regs + S3C_UDC_OTG_DIEPCTL(ep_num));
#endif

	__raw_writel(virt_to_phys(buf),
		udc->regs + S3C_UDC_OTG_DIEPDMA(ep_num));
	__raw_writel((pktcnt<<19)|(length<<0),
		udc->regs + S3C_UDC_OTG_DIEPTSIZ(ep_num));
	ctrl = __raw_readl(udc->regs + S3C_UDC_OTG_DIEPCTL(ep_num));

	if ((ctrl & DEPCTL_TYPE_MASK) == DEPCTL_ISO_TYPE) {
		if (ctrl & DEPCTL_EO_FRNUM)
			ctrl |= DEPCTL_SETD0PID;
		else
			ctrl |= DEPCTL_SETD1PID;
	}

	__raw_writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl,
		udc->regs + S3C_UDC_OTG_DIEPCTL(ep_num));

#ifndef DED_TX_FIFO
	ctrl = __raw_readl(udc->regs + S3C_UDC_OTG_DIEPCTL(EP0_CON));
	ctrl = (ctrl & ~(EP_MASK<<DEPCTL_NEXT_EP_BIT)) |
		(ep_num<<DEPCTL_NEXT_EP_BIT);
	__raw_writel(ctrl, udc->regs + S3C_UDC_OTG_DIEPCTL(EP0_CON));
#endif

	DEBUG_IN_EP("%s:EP%d TX DMA start : DIEPDMA0 = 0x%x,"
			"DIEPTSIZ0 = 0x%x, DIEPCTL0 = 0x%x\n"
			"\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n",
			__func__, ep_num,
			__raw_readl(udc->regs + S3C_UDC_OTG_DIEPDMA(ep_num)),
			__raw_readl(udc->regs + S3C_UDC_OTG_DIEPTSIZ(ep_num)),
			__raw_readl(udc->regs + S3C_UDC_OTG_DIEPCTL(ep_num)),
			buf, pktcnt, length);

	req->written_bytes = length;
	return length;
}
static int setdma_tx(struct s3c_ep *ep, struct s3c_request *req)
{
	u32 *buf, ctrl = 0;
	u32 length, pktcnt;
	u32 ep_num = ep_index(ep);
	u32 *p = the_controller->dma_buf[ep_index(ep)+1];

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

	if (ep_num == EP0_CON)
		length = min(length, (u32)ep_maxpacket(ep));

	ep->len = length;
	ep->dma_buf = buf;
	memcpy(p, ep->dma_buf, length);

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

	/* Flush the endpoint's Tx FIFO */
	writel(ep->fifo_num<<6, &reg->grstctl);
	writel((ep->fifo_num<<6)|0x20, &reg->grstctl);
	while (readl(&reg->grstctl) & 0x20)
		;

	/* Write the FIFO number to be used for this endpoint */
	ctrl = readl(&reg->in_endp[ep_num].diepctl);
	ctrl &= ~(0xF << 22);
	ctrl |= (ep_num << 22);
	writel(ctrl , &reg->in_endp[ep_num].diepctl);
#endif
	ctrl = readl(&reg->in_endp[ep_num].diepctl);


	DEBUG_IN_EP("%s: epindex %d setting diepdma to 0x%x\n",__func__,ep_index(ep),the_controller->dma_addr[ep_index(ep)+1]);
	writel(the_controller->dma_addr[ep_index(ep)+1],
	       &reg->in_endp[ep_num].diepdma);
	writel((pktcnt<<19)|(length<<0), &reg->in_endp[ep_num].dieptsiz);


	/* Clear reserved (Next EP) bits */
	ctrl = (ctrl&~(EP_MASK<<DEPCTL_NEXT_EP_BIT));
	writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, &reg->in_endp[ep_num].diepctl);

	ctrl = readl(&reg->in_endp[EP0_CON].diepctl);
	ctrl = (ctrl&~(EP_MASK<<DEPCTL_NEXT_EP_BIT))|(ep_num<<11);
	writel(ctrl, &reg->in_endp[EP0_CON].diepctl);


	DEBUG_IN_EP("%s:EP%d TX DMA start : DIEPDMA0 = 0x%x,"
		    "DIEPTSIZ0 = 0x%x, DIEPCTL0 = 0x%x\n"
		    "\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n",
		    __func__, ep_num,
		    readl(&reg->in_endp[ep_num].diepdma),
		    readl(&reg->in_endp[ep_num].dieptsiz),
		    readl(&reg->in_endp[ep_num].diepctl),
		    buf, pktcnt, length);

	return length;
}