예제 #1
0
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);

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

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

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

	writel(the_controller->dma_addr[ep_index(ep)+1],
	       &reg->in_endp[ep_num].diepdma);
	writel(DIEPT_SIZ_PKT_CNT(pktcnt) | DIEPT_SIZ_XFER_SIZE(length),
	       &reg->in_endp[ep_num].dieptsiz);

	ctrl = readl(&reg->in_endp[ep_num].diepctl);

	/* Write the FIFO number to be used for this endpoint */
	ctrl &= DIEPCTL_TX_FIFO_NUM_MASK;
	ctrl |= DIEPCTL_TX_FIFO_NUM(ep->fifo_num);

	/* 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);

	debug_cond(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;
}
예제 #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;
}
예제 #3
0
/** Write request to FIFO (max write == maxp size)
 *  Return:  0 = still running, 1 = completed, negative = errno
 *  NOTE: INDEX register must be set for EP
 */
static int write_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
{
	u32 max;
	u32 csr;

	max = le16_to_cpu(ep->desc->wMaxPacketSize);

	csr = usb_read(ep->csr1);
	DEBUG("CSR: %x %d\n", csr, csr & USB_IN_CSR1_FIFO_NOT_EMPTY);

	if (!(csr & USB_IN_CSR1_FIFO_NOT_EMPTY)) {
		unsigned count;
		int is_last, is_short;

		count = write_packet(ep, req, max);
		usb_set(USB_IN_CSR1_IN_PKT_RDY, ep->csr1);

		/* 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("%s: wrote %s %d bytes%s%s %d left %p\n", __FUNCTION__,
		      ep->ep.name, count,
		      is_last ? "/L" : "", is_short ? "/S" : "",
		      req->req.length - req->req.actual, req);

		/* requests complete when all IN data is in the FIFO */
		if (is_last) {
			done(ep, req, 0);
			if (list_empty(&ep->queue)) {
				pio_irq_disable(ep_index(ep));
			}
			return 1;
		}
	} else {
		DEBUG("Hmm.. %d ep FIFO is not empty!\n", ep_index(ep));
	}

	return 0;
}
예제 #4
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;
}
예제 #6
0
/** Write request to FIFO (max write == maxp size)
 *  Return:  0 = still running, 1 = completed, negative = errno
 */
static int write_fifo(struct elfin_ep *ep, struct elfin_request *req)
{
	u32 max;
	unsigned count;
	int is_last, is_short;

	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));
	}

	/* requests complete when all IN data is in the FIFO */
	if (is_last) {
		if(!ep_index(ep)){	// EP0 must not come here
			BUG();
			//usb_set(S3C2410_UDC_EP0_CSR_IPKRDY | S3C2410_UDC_EP0_CSR_DE, 
			//		S3C2410_UDC_EP0_CSR_REG, 0);
		}else{
			usb_set(S3C2410_UDC_ICSR1_PKTRDY, ep->csr1, ep_index(ep));
		}
		done(ep, req, 0);
		return 1;
	} else{
		usb_set(S3C2410_UDC_ICSR1_PKTRDY, ep->csr1, ep_index(ep));
	}

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

	return 0;
}
예제 #7
0
/* until it's enabled, this UDC should be completely invisible
 * to any USB host.
 */
static void udc_enable(struct lh7a40x_udc *dev)
{
	int ep;

	DEBUG("%s, %p\n", __FUNCTION__, dev);

	dev->gadget.speed = USB_SPEED_UNKNOWN;

#ifdef CONFIG_ARCH_LH7A404
	/* Set Port C bit 1 & 2 as output */
	set_portc_ddr(1, 1);
	set_portc_ddr(2, 1);

	/* Enable USB power */
	set_portc_dr(1, 0);
#endif

	/*
	 * C.f Chapter 18.1.3.1 Initializing the USB
	 */

	/* Disable the USB */
	usb_clear(PM_USB_ENABLE, USB_PM);

	/* Reset APB & I/O sides of the USB */
	usb_set(USB_RESET_APB | USB_RESET_IO, USB_RESET);
	mdelay(5);
	usb_clear(USB_RESET_APB | USB_RESET_IO, USB_RESET);

	/* Set MAXP values for each */
	for (ep = 0; ep < UDC_MAX_ENDPOINTS; ep++) {
		struct lh7a40x_ep *ep_reg = &dev->ep[ep];
		u32 csr;

		usb_set_index(ep);

		switch (ep_reg->ep_type) {
		case ep_bulk_in:
		case ep_interrupt:
			usb_clear(USB_IN_CSR2_USB_DMA_EN | USB_IN_CSR2_AUTO_SET,
				  ep_reg->csr2);
			/* Fall through */
		case ep_control:
			usb_write(BYTES2MAXP(ep_maxpacket(ep_reg)),
				  USB_IN_MAXP);
			break;
		case ep_bulk_out:
			usb_clear(USB_OUT_CSR2_USB_DMA_EN |
				  USB_OUT_CSR2_AUTO_CLR, ep_reg->csr2);
			usb_write(BYTES2MAXP(ep_maxpacket(ep_reg)),
				  USB_OUT_MAXP);
			break;
		}

		/* Read & Write CSR1, just in case */
		csr = usb_read(ep_reg->csr1);
		usb_write(csr, ep_reg->csr1);

		flush(ep_reg);
	}

	/* Disable interrupts */
	usb_write(0, USB_IN_INT_EN);
	usb_write(0, USB_OUT_INT_EN);
	usb_write(0, USB_INT_EN);

	/* Enable interrupts */
	usb_set(USB_IN_INT_EP0, USB_IN_INT_EN);
	usb_set(USB_INT_RESET_INT | USB_INT_RESUME_INT, USB_INT_EN);
	/* Dont enable rest of the interrupts */
	/* usb_set(USB_IN_INT_EP3 | USB_IN_INT_EP1 | USB_IN_INT_EP0, USB_IN_INT_EN);
	   usb_set(USB_OUT_INT_EP2, USB_OUT_INT_EN); */

	/* Enable SUSPEND */
	usb_set(PM_ENABLE_SUSPEND, USB_PM);

	/* Enable the USB */
	usb_set(PM_USB_ENABLE, USB_PM);

#ifdef CONFIG_ARCH_LH7A404
	/* NOTE: DOES NOT WORK! */
	/* Let host detect UDC:
	 * Software must write a 0 to the PMR:DCP_CTRL bit to turn this
	 * transistor on and pull the USBDP pin HIGH.
	 */
	/* usb_clear(PM_USB_DCP, USB_PM);
	   usb_set(PM_USB_DCP, USB_PM); */
#endif
}
예제 #8
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 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;
}