Exemple #1
0
/**
 * udc_startup - allow udc code to do any additional startup
 */
void udc_startup_events (struct usb_device_instance *device)
{
	/* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */
	usbd_device_event_irq (device, DEVICE_INIT, 0);

	/* The DEVICE_CREATE event puts the USB device in the state
	 * STATE_ATTACHED.
	 */
	usbd_device_event_irq (device, DEVICE_CREATE, 0);

	/* Some USB controller driver implementations signal
	 * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here.
	 * DEVICE_HUB_CONFIGURED causes a transition to the state STATE_POWERED,
	 * and DEVICE_RESET causes a transition to the state STATE_DEFAULT.
	 * The OMAP USB client controller has the capability to detect when the
	 * USB cable is connected to a powered USB bus via the ATT bit in the
	 * DEVSTAT register, so we will defer the DEVICE_HUB_CONFIGURED and
	 * DEVICE_RESET events until later.
	 */

	/* The GTA01 can detect usb device attachment, but we just assume being
	 * attached for now (go to STATE_POWERED) */
	usbd_device_event_irq (device, DEVICE_HUB_CONFIGURED, 0);

	udc_enable (device);
}
Exemple #2
0
/* Handle general USB interrupts and dispatch according to type.
 * This function implements TRM Figure 14-13.
 */
void S3C24X0_udc_irq(void)
{
	struct usb_endpoint_instance *ep0 = udc_device->bus->endpoint_array;
	u_int32_t save_idx = inl(S3C24X0_UDC_INDEX_REG);

	/* read interrupt sources */
	u_int32_t usb_status = inl(S3C24X0_UDC_USB_INT_REG);
	u_int32_t usbd_status = inl(S3C24X0_UDC_EP_INT_REG);

	debug("< IRQ usbs=0x%02x, usbds=0x%02x start > \n", usb_status, usbd_status);

	/* clear interrupts */
	outl(usb_status, S3C24X0_UDC_USB_INT_REG);

	if (usb_status & S3C24X0_UDC_USBINT_RESET) {
		//serial_putc('R');
		debug("RESET pwr=0x%x\n", inl(S3C24X0_UDC_PWR_REG));
		udc_setup_ep(udc_device, 0, ep0);
		outl(S3C24X0_UDC_EP0_CSR_SSE|S3C24X0_UDC_EP0_CSR_SOPKTRDY, S3C24X0_UDC_EP0_CSR_REG);
		ep0->state = EP0_IDLE;
		usbd_device_event_irq (udc_device, DEVICE_RESET, 0);
	}

	if (usb_status & S3C24X0_UDC_USBINT_RESUME) {
		debug("RESUME\n");
		usbd_device_event_irq(udc_device, DEVICE_BUS_ACTIVITY, 0);
	}

	if (usb_status & S3C24X0_UDC_USBINT_SUSPEND) {
		debug("SUSPEND\n");
		usbd_device_event_irq(udc_device, DEVICE_BUS_INACTIVE, 0);
	}

	/* Endpoint Interrupts */
	if (usbd_status) {
		int i;

		if (usbd_status & S3C24X0_UDC_INT_EP0) {
			outl(S3C24X0_UDC_INT_EP0, S3C24X0_UDC_EP_INT_REG);
			S3C24X0_udc_ep0();
		}

		for (i = 1; i < 5; i++) {
			u_int32_t tmp = 1 << i;

			if (usbd_status & tmp) {
				/* FIXME: Handle EP X */
				outl(tmp, S3C24X0_UDC_EP_INT_REG);
				S3C24X0_udc_epn(i);
			}
		}
	}
	S3C24X0_UDC_SETIX(save_idx);
}
Exemple #3
0
static void musb_peri_ep0_zero_data_request(int err)
{
	musb_peri_ep0_ack_req();

	if (err) {
		musb_peri_ep0_stall();
		SET_EP0_STATE(IDLE);
	} else {

		musb_peri_ep0_last();

		/* USBD state */
		switch (ep0_urb->device_request.bRequest) {
		case USB_REQ_SET_ADDRESS:
			if ((debug_setup) && (debug_level > 1))
				serial_printf("INFO : %s received set "
					      "address\n", __PRETTY_FUNCTION__);
			break;

		case USB_REQ_SET_CONFIGURATION:
			if ((debug_setup) && (debug_level > 1))
				serial_printf("INFO : %s Configured\n",
					      __PRETTY_FUNCTION__);
			usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
			break;
		}

		/* EP0 state */
		if (USB_REQ_SET_ADDRESS == ep0_urb->device_request.bRequest) {
			SET_EP0_STATE(SET_ADDRESS);
		} else {
			SET_EP0_STATE(IDLE);
		}
	}
}
Exemple #4
0
void udc_startup_events(struct usb_device_instance *device)
{
	/* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */
	usbd_device_event_irq(device, DEVICE_INIT, 0);

	/*
	 * The DEVICE_CREATE event puts the USB device in the state
	 * STATE_ATTACHED.
	 */
	usbd_device_event_irq(device, DEVICE_CREATE, 0);

	/* Resets the address to 0 */
	usbd_device_event_irq(device, DEVICE_RESET, 0);

	udc_enable(device);
}
Exemple #5
0
void usbd_device_event (struct usb_device_instance *device, usb_device_event_t event, int data)
{
	unsigned long flags;
	local_irq_save (flags);
	usbd_device_event_irq (device, event, data);
	local_irq_restore (flags);
}
/* udc_startup_events
 *
 * Enable the specified device
 */
void udc_startup_events (struct usb_device_instance *device)
{
	udc_enable (device);
	if (udc_state == STATE_READY) {
		usbd_device_event_irq (device, DEVICE_CREATE, 0);
	}
}
Exemple #7
0
/* Allow udc code to do any additional startup */
void udc_startup_events(struct usb_device_instance *device)
{
	/* The DEVICE_INIT event puts the USB device in the state STATE_INIT */
	usbd_device_event_irq(device, DEVICE_INIT, 0);

	/* The DEVICE_CREATE event puts the USB device in the state
	 * STATE_ATTACHED */
	usbd_device_event_irq(device, DEVICE_CREATE, 0);

	/* Some USB controller driver implementations signal
	 * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here.
	 * DEVICE_HUB_CONFIGURED causes a transition to the state
	 * STATE_POWERED, and DEVICE_RESET causes a transition to
	 * the state STATE_DEFAULT.
	 */
	udc_enable(device);
}
Exemple #8
0
static void usb_dev_hand_reset(void)
{
	u32 temp;
	temp = readl(USB_DEVICEADDR);
	temp &= ~0xfe000000;
	writel(temp, USB_DEVICEADDR);
	writel(readl(USB_ENDPTSETUPSTAT), USB_ENDPTSETUPSTAT);
	writel(readl(USB_ENDPTCOMPLETE), USB_ENDPTCOMPLETE);
	while (readl(USB_ENDPTPRIME))
		;
	writel(0xffffffff, USB_ENDPTFLUSH);
	DBG("reset-PORTSC=%x\n", readl(USB_PORTSC1));
	usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
}
Exemple #9
0
/**
 * udc_cable_event - called from cradle interrupt handler
 */
void udc_cable_event(void)
{
    struct usb_bus_instance *bus;
    struct usb_device_instance *device;
    struct bi_data *data;

    dbgENTER(dbgflg_usbdbi_init,1);

    // sanity check
    if (!(device = device_array[0]) || !(bus = device->bus) || !(data = bus->privdata)) {
        return;
    }

    {
        unsigned long flags;
        local_irq_save(flags);
        if (udc_connected()) {
            dbg_init(1, "state: %d connected: %d", device->device_state, 1);;
            if (device->device_state == STATE_ATTACHED) {
                dbg_init(1, "LOADING");
                usbd_device_event_irq(device, DEVICE_HUB_CONFIGURED, 0);
                usbd_device_event_irq(device, DEVICE_RESET, 0);
            }
        }
        else {
            dbg_init(1, "state: %d connected: %d", device->device_state, 0);;
            if (device->device_state != STATE_ATTACHED) {
                dbg_init(1, "UNLOADING");
                usbd_device_event_irq(device, DEVICE_RESET, 0);
                usbd_device_event_irq(device, DEVICE_POWER_INTERRUPTION, 0);
                usbd_device_event_irq(device, DEVICE_HUB_RESET, 0);
            }
        }
        local_irq_restore(flags);
    }
    dbgLEAVE(dbgflg_usbdbi_init,1);
}
Exemple #10
0
static void udc_state_changed(void)
{
	int config, interface, alternate;

	writel(readl(UDCCR) | UDCCR_SMAC, UDCCR);

	config = (readl(UDCCR) & UDCCR_ACN) >> UDCCR_ACN_S;
	interface = (readl(UDCCR) & UDCCR_AIN) >> UDCCR_AIN_S;
	alternate = (readl(UDCCR) & UDCCR_AAISN) >> UDCCR_AAISN_S;

	usbdbg("New UDC settings are: conf %d - inter %d - alter %d",
		config, interface, alternate);

	usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
	writel(UDCISR1_IRCC, UDCISR1);
}
Exemple #11
0
static void musb_peri_ep0_set_address(void)
{
	u8 faddr;
	writeb(udc_device->address, &musbr->faddr);

	/* Verify */
	faddr = readb(&musbr->faddr);
	if (udc_device->address == faddr) {
		SET_EP0_STATE(IDLE);
		usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0);
		if ((debug_setup) && (debug_level > 1))
			serial_printf("INFO : %s Address set to %d\n",
				      __PRETTY_FUNCTION__, udc_device->address);
	} else {
		if (debug_level > 0)
			serial_printf("ERROR : %s Address missmatch "
				      "sw %d vs hw %d\n",
				      __PRETTY_FUNCTION__,
				      udc_device->address, faddr);
	}
}
Exemple #12
0
static void S3C24X0_udc_ep0(void)
{
	u_int8_t ep0csr;
	struct usb_endpoint_instance *ep0 = udc_device->bus->endpoint_array;

	S3C24X0_UDC_SETIX(0);
	ep0csr = inl(S3C24X0_UDC_IN_CSR1_REG);

	/* clear stall status */
	if (ep0csr & S3C24X0_UDC_EP0_CSR_SENTSTL) {
	    	/* serial_printf("Clearing SENT_STALL\n"); */
		clear_ep0_sst();
		if (ep0csr & S3C24X0_UDC_EP0_CSR_SOPKTRDY)
			clear_ep0_opr();
		ep0->state = EP0_IDLE;
		return;
	}

	/* clear setup end */
	if (ep0csr & S3C24X0_UDC_EP0_CSR_SE
	    /* && ep0->state != EP0_IDLE */) {
	    	/* serial_printf("Clearing SETUP_END\n"); */
		clear_ep0_se();
#if 1
		if (ep0csr & S3C24X0_UDC_EP0_CSR_SOPKTRDY) {
			/* Flush FIFO */
			while (inl(S3C24X0_UDC_OUT_FIFO_CNT1_REG))
				inl(S3C24X0_UDC_EP0_FIFO_REG);
			clear_ep0_opr();
		}
#endif
		ep0->state = EP0_IDLE;
		return;
	}

	/* Don't ever put [serial] debugging in non-error codepaths here, it
	 * will violate the tight timing constraints of this USB Device
	 * controller (and lead to bus enumeration failures) */

	switch (ep0->state) {
		int i, fifo_count;
		unsigned char *datap;
	case EP0_IDLE:
		if (!(ep0csr & S3C24X0_UDC_EP0_CSR_OPKRDY))
			break;

		datap = (unsigned char *) &ep0_urb->device_request;
		/* host->device packet has been received */

		/* pull it out of the fifo */
		fifo_count = fifo_count_out();
		for (i = 0; i < fifo_count; i++) {
			*datap = (unsigned char)inl(S3C24X0_UDC_EP0_FIFO_REG);
			datap++;
		}
		if (fifo_count != 8) {
			debug("STRANGE FIFO COUNT: %u bytes\n", fifo_count);
			set_ep0_ss();
			return;
		}

		if (ep0_urb->device_request.wLength == 0) {
			if (ep0_recv_setup(ep0_urb)) {
				/* Not a setup packet, stall next EP0 transaction */
				debug("can't parse setup packet1\n");
				set_ep0_ss();
				set_ep0_de_out();
				ep0->state = EP0_IDLE;
				return;
			}
			/* There are some requests with which we need to deal
			 * manually here */
			switch (ep0_urb->device_request.bRequest) {
			case USB_REQ_SET_CONFIGURATION:
				if (!ep0_urb->device_request.wValue)
					usbd_device_event_irq(udc_device,
							DEVICE_DE_CONFIGURED, 0);
				else
					usbd_device_event_irq(udc_device,
							DEVICE_CONFIGURED, 0);
				break;
			case USB_REQ_SET_ADDRESS:
				udc_set_address(udc_device->address);
				usbd_device_event_irq(udc_device,
						DEVICE_ADDRESS_ASSIGNED, 0);
				break;
			default:
				break;
			}
			set_ep0_de_out();
			ep0->state = EP0_IDLE;
		} else {
			if ((ep0_urb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) {
				clear_ep0_opr();
				ep0->state = EP0_OUT_DATA_PHASE;
				ep0_urb->buffer = ep0_urb->buffer_data;
				ep0_urb->buffer_length = sizeof(ep0_urb->buffer_data);
				ep0_urb->actual_length = 0;
			} else {
				ep0->state = EP0_IN_DATA_PHASE;

				if (ep0_recv_setup(ep0_urb)) {
					/* Not a setup packet, stall next EP0 transaction */
					debug("can't parse setup packet2\n");
					set_ep0_ss();
					//set_ep0_de_out();
					ep0->state = EP0_IDLE;
					return;
				}
				clear_ep0_opr();
				ep0->tx_urb = ep0_urb;
				ep0->sent = ep0->last = 0;

				if (S3C24X0_write_noniso_tx_fifo(ep0)) {
					ep0->state = EP0_IDLE;
					set_ep0_de_in();
				} else
					set_ep0_ipr();
			}
		}
		break;
	case EP0_IN_DATA_PHASE:
		if (!(ep0csr & S3C24X0_UDC_EP0_CSR_IPKRDY)) {
			ep0->sent += ep0->last;

			if (S3C24X0_write_noniso_tx_fifo(ep0)) {
				ep0->state = EP0_IDLE;
				set_ep0_de_in();
			} else
				set_ep0_ipr();
		}
		break;
	case EP0_OUT_DATA_PHASE:
		if (ep0csr & S3C24X0_UDC_EP0_CSR_OPKRDY) {
			u32 urb_avail = ep0_urb->buffer_length - ep0_urb->actual_length;
			u_int8_t *cp = ep0_urb->buffer + ep0_urb->actual_length;
			int i, fifo_count;

			fifo_count = fifo_count_out();
			if (fifo_count < urb_avail)
				urb_avail = fifo_count;

			for (i = 0; i < urb_avail; i++)
				*cp++ = inl(S3C24X0_UDC_EP0_FIFO_REG);

			ep0_urb->actual_length += urb_avail;

			if (fifo_count < ep0->rcv_packetSize ||
			    ep0_urb->actual_length >= ep0_urb->device_request.wLength) {
				ep0->state = EP0_IDLE;
				if (ep0_recv_setup(ep0_urb)) {
					/* Not a setup packet, stall next EP0 transaction */
					debug("can't parse setup packet3\n");
					set_ep0_ss();
					//set_ep0_de_out();
					return;
				}
				set_ep0_de_out();
			} else
				clear_ep0_opr();
		}
		break;
	case EP0_END_XFER:
		ep0->state = EP0_IDLE;
		break;
	case EP0_STALL:
		//set_ep0_ss;
		ep0->state = EP0_IDLE;
		break;
	}
}
Exemple #13
0
static void mxc_udc_recv_setup(void)
{
	setup_packet *s = &ep0_urb->device_request;

	mxc_udc_read_setup_pkt(s);
	if (s->wLength)	{
		mxc_udc.ep0_dir = (s->bmRequestType & USB_DIR_IN) ?
					USB_DIR_OUT : USB_DIR_IN;
		mxc_udc_queue_update(0, NULL, 0, 0xffffffff);
	}
	if (ep0_recv_setup(ep0_urb)) {
		mxc_ep0_stall();
		return;
	}
	switch (s->bRequest) {
	case USB_REQ_GET_STATUS:
		if ((s->bmRequestType & (USB_DIR_IN | USB_TYPE_MASK)) !=
					 (USB_DIR_IN | USB_TYPE_STANDARD))
			break;
		ch9getstatus(s->bmRequestType, s->wValue,
				s->wIndex, s->wLength);
		return;
	case USB_REQ_SET_ADDRESS:
		if (s->bmRequestType != (USB_DIR_OUT |
			    USB_TYPE_STANDARD | USB_RECIP_DEVICE))
			break;
		mxc_udc.setaddr = 1;
		mxc_udc.ep0_dir = USB_DIR_IN;
		mxc_udc_queue_update(0, NULL, 0, 0xffffffff);
		usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0);
		return;
	case USB_REQ_SET_CONFIGURATION:
		usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
	case USB_REQ_CLEAR_FEATURE:
	case USB_REQ_SET_FEATURE:
	{
		int rc = -1;
		if ((s->bmRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) ==
				 (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD))
			rc = 0;
		else if ((s->bmRequestType &
			    (USB_RECIP_MASK | USB_TYPE_MASK)) ==
			     (USB_RECIP_DEVICE | USB_TYPE_STANDARD))
			rc = 0;
		else
			break;
		if (rc == 0) {
			mxc_udc.ep0_dir = USB_DIR_IN;
			mxc_udc_queue_update(0, NULL, 0, 0xffffffff);
		}
		return;
	}
	default:
		break;
	}
	if (s->wLength) {
		mxc_udc.ep0_dir = (s->bmRequestType & USB_DIR_IN) ?
					USB_DIR_IN : USB_DIR_OUT;
		mxc_udc_queue_update(0, ep0_urb->buffer,
				ep0_urb->actual_length, 0xffffffff);
		ep0_urb->actual_length = 0;
	} else {
		mxc_udc.ep0_dir = USB_DIR_IN;
		mxc_udc_queue_update(0, NULL, 0, 0xffffffff);
	}
}
Exemple #14
0
static void mxc_udc_recv_setup(void)
{
	struct usb_device_request *s = &ep0_urb->device_request;

	mxc_udc_read_setup_pkt(s);
	if (s->wLength)	{
		/* If has a data phase,
		  * then prime a dtd for status stage which has zero length DATA0.
		  * The direction of status stage should oppsite to direction of data phase.
		  */
		mxc_udc.ep0_dir = (s->bmRequestType & USB_DIR_IN) ?
					USB_DIR_OUT : USB_DIR_IN;
		mxc_udc_queue_update(0, NULL, 0, 0xffffffff);
	}
	if (ep0_recv_setup(ep0_urb)) {
		mxc_ep0_stall();
		return;
	}
	switch (s->bRequest) {
	case USB_REQ_GET_STATUS:
		if ((s->bmRequestType & (USB_DIR_IN | USB_TYPE_MASK)) !=
					 (USB_DIR_IN | USB_TYPE_STANDARD))
			break;
		ch9getstatus(s->bmRequestType, s->wValue,
				s->wIndex, s->wLength);

		DBG("[SETUP] REQ_GET_STATUS\n");
		return;
	case USB_REQ_SET_ADDRESS:
		if (s->bmRequestType != (USB_DIR_OUT |
			    USB_TYPE_STANDARD | USB_RECIP_DEVICE))
			break;
		mxc_udc.setaddr = 1;
		mxc_udc.ep0_dir = USB_DIR_IN;
		mxc_udc_queue_update(0, NULL, 0, 0xffffffff);
		usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0);
		DBG("[SETUP] REQ_SET_ADDRESS\n");
		return;
	case USB_REQ_SET_CONFIGURATION:
		usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
		DBG("[SETUP] REQ_SET_CONFIGURATION\n");
	case USB_REQ_CLEAR_FEATURE:
	case USB_REQ_SET_FEATURE:
	{
		int rc = -1;
		if ((s->bmRequestType & (USB_RECIP_MASK | USB_TYPE_MASK)) ==
				 (USB_RECIP_ENDPOINT | USB_TYPE_STANDARD))
			rc = 0;
		else if ((s->bmRequestType &
			    (USB_RECIP_MASK | USB_TYPE_MASK)) ==
			     (USB_RECIP_DEVICE | USB_TYPE_STANDARD))
			rc = 0;
		else
			break;
		if (rc == 0) {
			mxc_udc.ep0_dir = USB_DIR_IN;
			mxc_udc_queue_update(0, NULL, 0, 0xffffffff);
		}
		return;
	}
	default:
		break;
	}
	if (s->wLength) {
		mxc_udc.ep0_dir = (s->bmRequestType & USB_DIR_IN) ?
					USB_DIR_IN : USB_DIR_OUT;
		mxc_udc_queue_update(0, ep0_urb->buffer,
				ep0_urb->actual_length, 0xffffffff);
		ep0_urb->actual_length = 0;
	} else {
		mxc_udc.ep0_dir = USB_DIR_IN;
		mxc_udc_queue_update(0, NULL, 0, 0xffffffff);
	}
}
Exemple #15
0
/* Handle general USB interrupts and dispatch according to type.
 * This function implements TRM Figure 14-13.
 */
void s3c2410_udc_irq(void)
{
	struct usb_endpoint_instance *ep0 = udc_device->bus->endpoint_array;
	u_int32_t save_idx = inl(S3C2410_UDC_INDEX_REG), idx2;

	/* read interrupt sources */
	u_int32_t usb_status = inl(S3C2410_UDC_USB_INT_REG);
	u_int32_t usbd_status = inl(S3C2410_UDC_EP_INT_REG);

	u_int32_t pwr_reg = inl(S3C2410_UDC_PWR_REG);
	u_int32_t ep0csr = inl(S3C2410_UDC_IN_CSR1_REG);

	//debug("< IRQ usbs=0x%02x, usbds=0x%02x start >", usb_status, usbd_status);

	/* clear interrupts */
	outl(usb_status, S3C2410_UDC_USB_INT_REG);

	if (usb_status & S3C2410_UDC_USBINT_RESET) {
		//serial_putc('R');
		debug("RESET pwr=0x%x\n", inl(S3C2410_UDC_PWR_REG));
		udc_setup_ep(udc_device, 0, ep0);
		outl(S3C2410_UDC_EP0_CSR_SSE|S3C2410_UDC_EP0_CSR_SOPKTRDY, S3C2410_UDC_EP0_CSR_REG);
		ep0->state = EP0_IDLE;
		usbd_device_event_irq (udc_device, DEVICE_RESET, 0);
	}

	if (usb_status & S3C2410_UDC_USBINT_RESUME) {
		debug("RESUME\n");
		usbd_device_event_irq(udc_device, DEVICE_BUS_ACTIVITY, 0);
	}

	if (usb_status & S3C2410_UDC_USBINT_SUSPEND) {
		debug("SUSPEND\n");
		usbd_device_event_irq(udc_device, DEVICE_BUS_INACTIVE, 0);
	}

	/* Endpoint Interrupts */
	if (usbd_status) {
		int i;

		if (usbd_status & S3C2410_UDC_INT_EP0) {
			outl(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_REG);
			s3c2410_udc_ep0();
		}

		for (i = 1; i < 5; i++) {
			u_int32_t tmp = 1 << i;

			if (usbd_status & tmp) {
				/* FIXME: Handle EP X */
				outl(tmp, S3C2410_UDC_EP_INT_REG);
				s3c2410_udc_epn(i);
			}
		}

		usbd_status = inl(S3C2410_UDC_EP_INT_REG);
		/* what else causes this interrupt? a receive! who is it? */
		if (!usb_status && !usbd_status && !pwr_reg && !ep0csr) {
			debug("dual packet issue\n");
			for (i = 1; i < 5; i++) {
				idx2 = inl(S3C2410_UDC_INDEX_REG);
				outl(i, S3C2410_UDC_INDEX_REG);

				if (inl(S3C2410_UDC_OUT_CSR1_REG) & 0x1)
					s3c2410_udc_epn(i);

				/* restore index */
				outl(idx2, S3C2410_UDC_INDEX_REG);
			}
		}

	}
	S3C2410_UDC_SETIX(save_idx);
}
Exemple #16
0
/**
 * bi_device_event - handle generic bus event
 * @device: device pointer
 * @event: interrupt event
 *
 * Called by usb core layer to inform bus of an event.
 */
int bi_device_event(struct usb_device_instance *device, usb_device_event_t event, int data)
{
    sie_info * sie_data;
    cy_priv_t * cy_priv;
    otg_t * otg;

    sie_data = (sie_info *) device->bus->privdata;
    cy_priv = (cy_priv_t *) sie_data->cy_priv;
    otg = (otg_t *) cy_priv->otg;

    //printk(KERN_DEBUG "bi_device_event: event: %d\n", event);

    if (!device) {
        return 0;
    }
    switch (event) {
    case DEVICE_UNKNOWN:
        break;
    case DEVICE_INIT:
        break;
    case DEVICE_CREATE:         // XXX should this stuff be in DEVICE_INIT?

        bi_config(device);

        // enable udc, enable interrupts, enable connect
        udc_enable(device);
        udc_all_interrupts(device);
        udc_connect();
        break;

    case DEVICE_HUB_CONFIGURED:
        break;

    case DEVICE_RESET:
        device->address = 0;
        udc_set_address(device->address, device);
        udc_reset_ep(0, device);
        udc_all_interrupts(device); // XXX
        break;


    case DEVICE_ADDRESS_ASSIGNED:
        udc_set_address(device->address, device);
        device->status = USBD_OK;
        break;

    case DEVICE_CONFIGURED:
        bi_config(device);
        break;

    case DEVICE_DE_CONFIGURED:
        udc_reset_ep(1, device);
        udc_reset_ep(2, device);
        udc_reset_ep(3, device);
        break;

    case DEVICE_SET_INTERFACE:
        bi_config(device);
        break;

    case DEVICE_SET_FEATURE:
        break;

    case DEVICE_CLEAR_FEATURE:
        break;

    case DEVICE_BUS_INACTIVE:
        // disable suspend interrupt
        udc_suspended_interrupts(device);

        // XXX check on linkup and sl11
        // if we are no longer connected then force a reset
        if (!udc_connected()) {
            usbd_device_event_irq(device, DEVICE_RESET, 0);
        }
        break;

    case DEVICE_BUS_ACTIVITY:
        // enable suspend interrupt
        udc_all_interrupts(device);
        break;

    case DEVICE_POWER_INTERRUPTION:
        break;

    case DEVICE_HUB_RESET:
        break;

    case DEVICE_DESTROY:
        udc_disconnect();
        bi_disable_endpoints(device);
        udc_disable_interrupts(device);
        udc_disable();
        break;

    case DEVICE_BUS_REQUEST:
        otg->b_bus_req = TRUE;
        update_otg_state(otg);
        break;

    case DEVICE_BUS_RELEASE:
        otg->b_bus_req = FALSE;
        update_otg_state(otg);
        break;

    case DEVICE_RCV_URB_RECYCLED:
        udc_rcv_urb_recycled();
        break;

    case DEVICE_ACCEPT_HNP:
        otg->b_hnp_en = TRUE;
        update_otg_state(otg);
    break;

    case DEVICE_REQUEST_SRP:
        //otg->srp_start_flag = TRUE;
        otg->b_bus_req = TRUE;
        otg->b_se0_srp = TRUE;
        update_otg_state(otg);
    break;

    case DEVICE_FUNCTION_PRIVATE:
        break;
    }

    return 0;
}
Exemple #17
0
/**
 * bi_device_event - handle generic bus event
 * @device: device pointer
 * @event: interrupt event
 *
 * Called by usb core layer to inform bus of an event.
 */
int bi_device_event (struct usb_device_instance *device, usb_device_event_t event, int data)
{

	//printk(KERN_DEBUG "bi_device_event: event: %d\n", event);

	if (!device) {
		return 0;
	}

        dbg_usbe (1,"%s", USBD_DEVICE_EVENTS(event));

	switch (event) {
	case DEVICE_UNKNOWN:
		break;
	case DEVICE_INIT:
		break;
	case DEVICE_CREATE:	// XXX should this stuff be in DEVICE_INIT?
		// enable upstream port

		//ep0_enable(device);

		// for net_create
		bi_config (device);

		// enable udc, enable interrupts, enable connect
                printk(KERN_INFO"bi_device_event: call udc_enable\n");
		udc_enable (device);
                printk(KERN_INFO"bi_device_event: call udc_all_interrupts\n");

                // XXX verify
		udc_suspended_interrupts (device);
		//udc_all_interrupts (device);

		dbg_usbe (1, "CREATE done");
		break;

	case DEVICE_HUB_CONFIGURED:
		udc_connect ();
		break;

	case DEVICE_RESET:
		device->address = 0;
		udc_set_address (device->address);
		udc_reset_ep (0);
                
                // XXX verify
		udc_suspended_interrupts (device);
		dbg_usbe (1, "DEVICE RESET done: %d", device->address);
		break;


	case DEVICE_ADDRESS_ASSIGNED:
		udc_set_address (device->address);
		device->status = USBD_OK;

                // XXX verify
		udc_all_interrupts (device);	// XXX
		break;

	case DEVICE_CONFIGURED:
		device->status = USBD_OK;
		bi_config (device);
		break;

	case DEVICE_DE_CONFIGURED:
		{
			int ep;

			for (ep = 1; ep < udc_max_endpoints (); ep++)
				udc_reset_ep (ep);
		}
		break;


	case DEVICE_SET_INTERFACE:
		bi_config (device);
		break;

	case DEVICE_SET_FEATURE:
		break;

	case DEVICE_CLEAR_FEATURE:
		break;

	case DEVICE_BUS_INACTIVE:
		// disable suspend interrupt
		udc_suspended_interrupts (device);

		// XXX check on linkup and sl11
		// if we are no longer connected then force a reset
		if (!udc_connected ()) {
			usbd_device_event_irq (device, DEVICE_RESET, 0);
		}
		break;

	case DEVICE_BUS_ACTIVITY:
		// enable suspend interrupt
		udc_all_interrupts (device);
		break;

	case DEVICE_POWER_INTERRUPTION:
		break;

	case DEVICE_HUB_RESET:
		break;

	case DEVICE_DESTROY:
		udc_disconnect ();
		bi_disable_endpoints (device);
		udc_disable_interrupts (device);
		udc_disable ();
		break;

	case DEVICE_FUNCTION_PRIVATE:
		break;
	}
	return 0;
}
Exemple #18
0
void udc_irq(void)
{
	/* This is a high freq called function */
	if (enabled) {
		u8 intrusb;

		intrusb = readb(&musbr->intrusb);

		/*
		 * See drivers/usb/gadget/mpc8xx_udc.c for
		 * state diagram going from detached through
		 * configuration.
		 */
		if (MUSB_INTR_RESUME & intrusb) {
			usbd_device_event_irq(udc_device,
					      DEVICE_BUS_ACTIVITY, 0);
			musb_peri_resume();
		}

		musb_peri_ep0();

		if (MUSB_INTR_RESET & intrusb) {
			usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
			musb_peri_reset();
		}

		if (MUSB_INTR_DISCONNECT & intrusb) {
			/* cable unplugged from hub/host */
			usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
			musb_peri_reset();
			usbd_device_event_irq(udc_device, DEVICE_HUB_RESET, 0);
		}

		if (MUSB_INTR_SOF & intrusb) {
			usbd_device_event_irq(udc_device,
					      DEVICE_BUS_ACTIVITY, 0);
			musb_peri_resume();
		}

		if (MUSB_INTR_SUSPEND & intrusb) {
			usbd_device_event_irq(udc_device,
					      DEVICE_BUS_INACTIVE, 0);
		}

		if (ep0_state != SET_ADDRESS) {
			u16 intrrx, intrtx;

			intrrx = readw(&musbr->intrrx);
			intrtx = readw(&musbr->intrtx);

			if (intrrx)
				musb_peri_rx(intrrx);

			if (intrtx)
				musb_peri_tx(intrtx);
		} else {
			if (MUSB_INTR_SOF & intrusb) {
				u8 faddr;
				faddr = readb(&musbr->faddr);
				/*
				 * Setting of the address can fail.
				 * Normally it succeeds the second time.
				 */
				if (udc_device->address != faddr)
					musb_peri_ep0_set_address();
			}
		}
	}
}
Exemple #19
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;
}
Exemple #20
0
void udc_irq(void)
{
	int handled;
	struct usb_endpoint_instance *endpoint;
	int ep_num, i;
	u32 udcisr0;

	do {
		handled = 0;
		/* Suspend Interrupt Request */
		if (readl(USIR1) & UDCCR_SUSIR) {
			usbdbg("Suspend\n");
			udc_ack_int_UDCCR(UDCCR_SUSIR);
			handled = 1;
			ep0state = EP0_IDLE;
		}

		/* Resume Interrupt Request */
		if (readl(USIR1) & UDCCR_RESIR) {
			udc_ack_int_UDCCR(UDCCR_RESIR);
			handled = 1;
			usbdbg("USB resume\n");
		}

		if (readl(USIR1) & (1<<31)) {
			handled = 1;
			udc_state_changed();
		}

		/* Reset Interrupt Request */
		if (readl(USIR1) & UDCCR_RSTIR) {
			udc_ack_int_UDCCR(UDCCR_RSTIR);
			handled = 1;
			usbdbg("Reset\n");
			usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
		} else {
			if (readl(USIR0))
				usbdbg("UISR0: %x \n", readl(USIR0));

			if (readl(USIR0) & 0x2)
				writel(0x2, USIR0);

			/* Control traffic */
			if (readl(USIR0)  & USIR0_IR0) {
				handled = 1;
				writel(USIR0_IR0, USIR0);
				udc_handle_ep0(udc_device->bus->endpoint_array);
			}

			endpoint = udc_device->bus->endpoint_array;
			for (i = 0; i < udc_device->bus->max_endpoints; i++) {
				ep_num = (endpoint[i].endpoint_address) &
						USB_ENDPOINT_NUMBER_MASK;
				if (!ep_num)
					continue;
				udcisr0 = readl(UDCISR0);
				if (udcisr0 &
					UDCISR_INT(ep_num, UDC_INT_PACKETCMP)) {
					writel(UDCISR_INT(ep_num, UDC_INT_PACKETCMP),
					       UDCISR0);
					udc_handle_ep(&endpoint[i]);
				}
			}
		}

	} while (handled);
}