Example #1
0
/**
 * elfin_in_epn - handle IN interrupt
 */
static void elfin_in_epn(struct elfin_udc *dev, u32 ep_idx)
{
	u32 csr;
	struct elfin_ep *ep = &dev->ep[ep_idx];
	struct elfin_request *req;

	csr = usb_read(ep->csr1, ep_index(ep));
	DPRINTK("%s: %d, csr %x\n", __FUNCTION__, ep_idx, csr);

	if (csr & S3C2410_UDC_ICSR1_SENTSTL) {
		printk("S3C2410_UDC_ICSR1_SENTSTL\n");
		usb_set(S3C2410_UDC_ICSR1_SENTSTL /*| S3C2410_UDC_ICSR1_SENDSTL */ ,
			ep->csr1, ep_index(ep));
		return;
	}

	if (!ep->desc) {
		DPRINTK("%s: NO EP DESC\n", __FUNCTION__);
		return;
	}

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

	DPRINTK("req: %p\n", req);

	if (!req)
		return;

	write_fifo(ep, req);
}
Example #2
0
/**
 * lh7a40x_in_epn - handle IN interrupt
 */
static void lh7a40x_in_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
{
	u32 csr;
	struct lh7a40x_ep *ep = &dev->ep[ep_idx];
	struct lh7a40x_request *req;

	usb_set_index(ep_idx);

	csr = usb_read(ep->csr1);
	DEBUG("%s: %d, csr %x\n", __FUNCTION__, ep_idx, csr);

	if (csr & USB_IN_CSR1_SENT_STALL) {
		DEBUG("USB_IN_CSR1_SENT_STALL\n");
		usb_set(USB_IN_CSR1_SENT_STALL /*|USB_IN_CSR1_SEND_STALL */ ,
			ep->csr1);
		return;
	}

	if (!ep->desc) {
		DEBUG("%s: NO EP DESC\n", __FUNCTION__);
		return;
	}

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

	DEBUG("req: %p\n", req);

	if (!req)
		return;

	write_fifo(ep, req);
}
Example #3
0
/** Read to request from FIFO (max read == bytes in fifo)
 *  Return:  0 = still running, 1 = completed, negative = errno
 *  NOTE: INDEX register must be set for EP
 */
static int read_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
{
	u32 csr;
	u8 *buf;
	unsigned bufferspace, count, is_short;
	volatile u32 *fifo = (volatile u32 *)ep->fifo;

	/* make sure there's a packet in the FIFO. */
	csr = usb_read(ep->csr1);
	if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY)) {
		DEBUG("%s: Packet NOT ready!\n", __func__);
		return -EINVAL;
	}

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

	/* read all bytes from this packet */
	count = usb_read(USB_OUT_FIFO_WC1);
	req->req.actual += min(count, bufferspace);

	is_short = (count < ep->ep.maxpacket);
	DEBUG("read %s %02x, %d bytes%s req %p %d/%d\n",
	      ep->ep.name, csr, count,
	      is_short ? "/S" : "", req, req->req.actual, req->req.length);

	while (likely(count-- != 0)) {
		u8 byte = (u8) (*fifo & 0xff);

		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(KERN_WARNING "%s overflow %d\n",
				       ep->ep.name, count);
			req->req.status = -EOVERFLOW;
		} else {
			*buf++ = byte;
			bufferspace--;
		}
	}

	usb_clear(USB_OUT_CSR1_OUT_PKT_RDY, ep->csr1);

	/* completion */
	if (is_short || req->req.actual == req->req.length) {
		done(ep, req, 0);
		usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1);

		if (list_empty(&ep->queue))
			pio_irq_disable(ep_index(ep));
		return 1;
	}

	/* finished that packet.  the next one may be waiting... */
	return 0;
}
Example #4
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;
}
Example #5
0
/** Enable EP interrupt */
static void pio_irq_enable(int ep)
{
	DEBUG("%s: %d\n", __FUNCTION__, ep);

	switch (ep) {
	case 1:
		usb_set(USB_IN_INT_EP1, USB_IN_INT_EN);
		break;
	case 2:
		usb_set(USB_OUT_INT_EP2, USB_OUT_INT_EN);
		break;
	case 3:
		usb_set(USB_IN_INT_EP3, USB_IN_INT_EN);
		break;
	default:
		DEBUG("Unknown endpoint: %d\n", ep);
		break;
	}
}
Example #6
0
/** Flush EP
 * NOTE: INDEX register must be set before this call
 */
static void flush(struct lh7a40x_ep *ep)
{
	DEBUG("%s, %p\n", __FUNCTION__, ep);

	switch (ep->ep_type) {
	case ep_control:
		/* check, by implication c.f. 15.1.2.11 */
		break;

	case ep_bulk_in:
	case ep_interrupt:
		/* if(csr & USB_IN_CSR1_IN_PKT_RDY) */
		usb_set(USB_IN_CSR1_FIFO_FLUSH, ep->csr1);
		break;

	case ep_bulk_out:
		/* if(csr & USB_OUT_CSR1_OUT_PKT_RDY) */
		usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1);
		break;
	}
}
Example #7
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;
}
Example #8
0
/** 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;
	unsigned count;
	int is_last = 0, is_short = 0;

#if TX_DMA_MODE
	if(tx_dmaStart) return 0;
	if ((req->req.actual == 0) && (req->req.length > ep->ep.maxpacket) && (!tx_dmaStart)) {

		DEBUG("TX_DMA_Start:: %s: read %s, bytes req %p %d/%d\n",
		__FUNCTION__, ep->ep.name, req, req->req.actual, req->req.length);

		usb_set(S3C_DMA_ENABLE,
				(u32) S3C_UDC_FCON_REG, ep_index(ep));

		usb_write(ep->ep.maxpacket, (u32) S3C_UDC_MAXP_REG, ep_index(ep));
		usb_write(ep->ep.maxpacket, (u32) S3C_UDC_BYTE_WRITE_CNT_REG, ep_index(ep));
		
		usb_set((u16)req->req.length,
				(u32) S3C_UDC_DMA_TOTAL_CNT1_REG, ep_index(ep));
		
		usb_set((u16)((req->req.length)>>16),
				(u32) S3C_UDC_DMA_TOTAL_CNT2_REG, ep_index(ep));

		usb_set(virt_to_phys(req->req.buf),
				(u32) S3C_UDC_DMA_MEM_BASE_ADDR_REG, ep_index(ep));
		
		usb_set(ep->ep.maxpacket,
				(u32) S3C_UDC_DMA_CNT_REG, ep_index(ep));
		
		usb_set(ep->ep.maxpacket,
				(u32) S3C_UDC_DMA_FIFO_CNT_REG, ep_index(ep));

		usb_set(S3C_MAX_BURST_INCR16,
				(u32) S3C_UDC_DMA_IF_CON_REG, ep_index(ep));

		usb_set(S3C_DMA_FLY_ENABLE|S3C_DMA_TX_START|S3C_USB_DMA_MODE,
				(u32) S3C_UDC_DMA_CON_REG, ep_index(ep));
		tx_dmaStart = 1;

		udelay(600);
		
	}
Example #9
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
}