Ejemplo n.º 1
0
/* Called to start packet transmission. */
int udc_endpoint_write (struct usb_endpoint_instance *endpoint)
{
	unsigned short epnum =
		endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;

	debug("Entering for ep %x \n", epnum);

	if (endpoint->tx_urb) {
		u32 ep_csr1;
		debug_urb_buffer("We have an URB, transmitting", endpoint);

		S3C24X0_write_noniso_tx_fifo(endpoint);

		S3C24X0_UDC_SETIX(epnum);

		ep_csr1 = inl(S3C24X0_UDC_IN_CSR1_REG);
		outl(ep_csr1|S3C24X0_UDC_ICSR1_PKTRDY, S3C24X0_UDC_IN_CSR1_REG);
	} else
		debug("\n");
	return 0;
}
Ejemplo n.º 2
0
static void S3C24X0_udc_epn(int ep)
{
	struct usb_endpoint_instance *endpoint;
	struct urb *urb;
	u32 ep_csr1;

	if (ep >= S3C24X0_UDC_NUM_ENDPOINTS)
		return;

	endpoint = &udc_device->bus->endpoint_array[ep];

	S3C24X0_UDC_SETIX(ep);

	if (endpoint->endpoint_address & USB_DIR_IN) {
		/* IN transfer (device to host) */
		ep_csr1 = inl(S3C24X0_UDC_IN_CSR1_REG);
		debug("for ep=%u, CSR1=0x%x ", ep, ep_csr1);

		urb = endpoint->tx_urb;
		if (ep_csr1 & S3C24X0_UDC_ICSR1_SENTSTL) {
			/* Stall handshake */
			debug("stall\n");
			outl(0x00, S3C24X0_UDC_IN_CSR1_REG);
			return;
		}
		if (!(ep_csr1 & S3C24X0_UDC_ICSR1_PKTRDY) && urb &&
		      urb->actual_length) {

			debug("completing previously send data ");
			usbd_tx_complete(endpoint);

			/* push pending data into FIFO */
			if ((endpoint->last == endpoint->tx_packetSize) &&
			    (urb->actual_length - endpoint->sent - endpoint->last == 0)) {
				endpoint->sent += endpoint->last;
				/* Write 0 bytes of data (ZLP) */
				debug("ZLP ");
				outl(ep_csr1|S3C24X0_UDC_ICSR1_PKTRDY, S3C24X0_UDC_IN_CSR1_REG);
			} else {
				/* write actual data to fifo */
				debug_urb_buffer("TX_DATA", endpoint);
				S3C24X0_write_noniso_tx_fifo(endpoint);
				outl(ep_csr1|S3C24X0_UDC_ICSR1_PKTRDY, S3C24X0_UDC_IN_CSR1_REG);
			}
		}
		debug("\n");
	} else {
		/* OUT transfer (host to device) */
		ep_csr1 = inl(S3C24X0_UDC_OUT_CSR1_REG);
		debug("for ep=%u, CSR1=0x%x ", ep, ep_csr1);

		urb = endpoint->rcv_urb;
		if (ep_csr1 & S3C24X0_UDC_OCSR1_SENTSTL) {
			/* Stall handshake */
			outl(0x00, S3C24X0_UDC_IN_CSR1_REG);
			return;
		}
		if ((ep_csr1 & S3C24X0_UDC_OCSR1_PKTRDY) && urb) {
			/* Read pending data from fifo */
			u32 fifo_count = fifo_count_out();
			int is_last = 0;
			u32 i, urb_avail = urb->buffer_length - urb->actual_length;
			u8 *cp = urb->buffer + urb->actual_length;

			if (fifo_count < endpoint->rcv_packetSize)
				is_last = 1;

			debug("fifo_count=%u is_last=%, urb_avail=%u)\n",
				fifo_count, is_last, urb_avail);

			if (fifo_count < urb_avail)
				urb_avail = fifo_count;

			for (i = 0; i < urb_avail; i++)
				*cp++ = inb(ep_fifo_reg[ep]);

			if (is_last)
				outl(ep_csr1 & ~S3C24X0_UDC_OCSR1_PKTRDY,
				     S3C24X0_UDC_OUT_CSR1_REG);

			usbd_rcv_complete(endpoint, urb_avail, 0);
		}
	}

	urb = endpoint->rcv_urb;
}
Ejemplo n.º 3
0
static void s3c2410_udc_epn(int ep)
{
	struct usb_endpoint_instance *endpoint;
	struct urb *urb;
	u32 ep_csr1;

	if (ep >= S3C2410_UDC_NUM_ENDPOINTS)
		return;

	endpoint = &udc_device->bus->endpoint_array[ep];

	S3C2410_UDC_SETIX(ep);

	if (endpoint->endpoint_address & USB_DIR_IN) {
		/* IN transfer (device to host) */
		ep_csr1 = inl(S3C2410_UDC_IN_CSR1_REG);
		debug("for ep=%u, IN_CSR1=0x%x ", ep, ep_csr1);

		urb = endpoint->tx_urb;
		if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) {
			/* Stall handshake */
			debug("stall\n");
			outl(0x00, S3C2410_UDC_IN_CSR1_REG);
			return;
		}
		if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && urb &&
		      urb->actual_length) {

			debug("completing previously send data ");
			usbd_tx_complete(endpoint);

			/* push pending data into FIFO */
			if ((endpoint->last == endpoint->tx_packetSize) &&
			    (urb->actual_length - endpoint->sent - endpoint->last == 0)) {
				endpoint->sent += endpoint->last;
				/* Write 0 bytes of data (ZLP) */
				debug("ZLP ");
				outl(ep_csr1|S3C2410_UDC_ICSR1_PKTRDY, S3C2410_UDC_IN_CSR1_REG);
			} else {
				/* write actual data to fifo */
				debug_urb_buffer("TX_DATA", endpoint);
				s3c2410_write_noniso_tx_fifo(endpoint);
				outl(ep_csr1|S3C2410_UDC_ICSR1_PKTRDY, S3C2410_UDC_IN_CSR1_REG);
			}
		}
		debug("\n");
	} else {
		/* OUT transfer (host to device) */
		ep_csr1 = inl(S3C2410_UDC_OUT_CSR1_REG);
		debug("for ep=%u, OUT_CSR1=0x%x ", ep, ep_csr1);

		urb = endpoint->rcv_urb;
		if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) {
			/* Stall handshake */
			debugX("SENT STALL\n");
			outl(0x00, S3C2410_UDC_IN_CSR1_REG);
			return;
		}
		if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && urb) {
			/* Read pending data from fifo */
			u32 fifo_count = fifo_count_out();
			int is_last = 0;
			u32 i, urb_avail = urb->buffer_length - urb->actual_length;
			u8 *cp = urb->buffer + urb->actual_length;

			if (fifo_count < endpoint->rcv_packetSize)
				is_last = 1;

			debug("fifo_count=%u is_last=%d, urb_avail=%u\n",
				fifo_count, is_last, urb_avail);

			if (fifo_count < urb_avail)
				urb_avail = fifo_count;

			for (i = 0; i < urb_avail; i++)
				*cp++ = inb(ep_fifo_reg[ep]);

			/* if (is_last) */
			/*
			 * Once the MCU reads the packet from FIFO,
			 * this bit should be cleared
			 */
#ifndef AUTO_CLEAR 
			outl(ep_csr1 & ~S3C2410_UDC_OCSR1_PKTRDY,
				     S3C2410_UDC_OUT_CSR1_REG);
#endif

			usbd_rcv_complete(endpoint, urb_avail, 0);
			/* FIXME is there a better way to notify that,
			 * we have got data */
			usbd_device_event_irq(udc_device,
						DEVICE_FUNCTION_PRIVATE, 0);
		}
	}

	urb = endpoint->rcv_urb;
}