Example #1
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);
}
Example #2
0
/* bi_modinit - commission bus interface driver
 */
int __init bi_modinit(void)
{
    struct usb_bus_instance * bus;
    struct usb_device_instance * device;
    //extern const char __usbd_module_info[];

    //printk(KERN_INFO "%s (dbg=\"%s\")\n", __usbd_module_info, dbg?dbg:"");

    if (0 != scan_debug_options("usb-bus",dbg_table,dbg)) {
        printk("Failed to scan dbg in bi_modinit\n");
    }

    if (bi_udc_init()) {
        return(-EINVAL);
    }

    // register this bus interface driver and create the device driver instance
    if ((bus = usbd_register_bus(&bi_driver))==NULL) {
        bi_udc_exit();
        return -EINVAL;
    }

    // see if we can scrounge up something to set a sort of unique device
    // address
    if (!udc_serial_init(bus)) {
        dbg_init(1,"serial: %s %04x", bus->serial_number_str,
                 bus->serial_number);
    }

    if ((device = usbd_register_device(NULL, bus, 8))==NULL) {
        usbd_deregister_bus(bus);
        bi_udc_exit();
        return -EINVAL;
    }

#ifdef CONFIG_PM
    // register with power management
    pm_dev = pm_register(PM_USB_DEV, PM_SYS_UNKNOWN, bi_pm_event);
    pm_dev->data = device;
#endif

    bus->device = device;
    device_array[0] = device;

    // initialize the device
    {
        struct usb_endpoint_instance *endpoint = device->bus->endpoint_array + 0;

        // setup endpoint zero

        endpoint->endpoint_address = 0;

        endpoint->tx_attributes = 0;
        endpoint->tx_transferSize = 255;
        endpoint->tx_packetSize = udc_ep0_packetsize();

        endpoint->rcv_attributes = 0;
        endpoint->rcv_transferSize = 0x8;
        endpoint->rcv_packetSize = udc_ep0_packetsize();

        udc_setup_ep(device, 0, endpoint);
    }

    // hopefully device enumeration will finish this process
    udc_startup_events(device);

#ifdef CONFIG_PM
    dbg_pm(0,"pm_dev->callback#%p",pm_dev->callback);
    if (!udc_connected()) {
       /* Fake a call from the PM system to suspend the UDC until it
           is needed (cable connect, etc) */
        (void) bi_pm_event(pm_dev,PM_SUSPEND,NULL);
    /* There appears to be no constant for this, but inspection
           of arch/arm/mach-l7200/apm.c:send_event() shows that the
           suspended state is 3 (i.e. pm_send_all(PM_SUSPEND, (void *)3))
           corresponding to ACPI_D3. */
    pm_dev->state = 3;
    }
#endif
    if (dbgflg_usbdbi_tick > 0) {
        // start ticker
        ticker_kickoff();
    }

    dbgLEAVE(dbgflg_usbdbi_init,1);
    return 0;
}
Example #3
0
/* bi_modinit - commission bus interface driver
 */
static int __init bi_modinit (void)
{
	extern const char __usbd_module_info[];
	struct usb_bus_instance *bus;
	struct usb_device_instance *device;
	struct bi_data *data;


	printk (KERN_INFO "%s (dbg=\"%s\")\n", __usbd_module_info, dbg ? dbg : "");

	// process debug options
	if (0 != scan_debug_options ("usbd-bi", dbg_table, dbg)) {
		return -EINVAL;
	}
	// check if we can see the UDC
	if (bi_udc_init ()) {
		return -EINVAL;
	}
	// allocate a bi private data structure
	if ((data = kmalloc (sizeof (struct bi_data), GFP_KERNEL)) == NULL) {
		bi_udc_exit ();
		return -EINVAL;
	}
	memset (data, 0, sizeof (struct bi_data));

	// register this bus interface driver and create the device driver instance
	if ((bus = usbd_register_bus (&bi_driver)) == NULL) {
		kfree (data);
		bi_udc_exit ();
		return -EINVAL;
	}

	bus->privdata = data;

	// see if we can scrounge up something to set a sort of unique device address
	if (!udc_serial_init (bus)) {
		dbg_init (1, "serial: %s %04x\n", bus->serial_number_str, bus->serial_number);
	}


	if ((device = usbd_register_device (NULL, bus, 8)) == NULL) {
		usbd_deregister_bus (bus);
		kfree (data);
		bi_udc_exit ();
		return -EINVAL;
	}
#if defined(CONFIG_PM) && !defined(CONFIG_USBD_MONITOR) && !defined(CONFIG_USBD_MONITOR_MODULE)
	// register with power management 
	pm_dev = pm_register (PM_USB_DEV, PM_SYS_UNKNOWN, bi_pm_event);
	pm_dev->data = device;
#endif

#ifdef CONFIG_DPM	/* MVL-CEE */
	bi_udc_ldm_driver_register();
	bi_udc_ldm_device_register();
#endif

	bus->device = device;
	device_array[0] = device;

	// initialize the device
	{
		struct usb_endpoint_instance *endpoint = device->bus->endpoint_array + 0;

		// setup endpoint zero

		endpoint->endpoint_address = 0;

		endpoint->tx_attributes = 0;
		endpoint->tx_transferSize = 255;
		endpoint->tx_packetSize = udc_ep0_packetsize ();

		endpoint->rcv_attributes = 0;
		endpoint->rcv_transferSize = 0x8;
		endpoint->rcv_packetSize = udc_ep0_packetsize ();

		udc_setup_ep (device, 0, endpoint);
	}

	// hopefully device enumeration will finish this process
        printk(KERN_INFO"bi_modinit: call udc_startup_events\n");
	udc_startup_events (device);

#if defined(CONFIG_PM) && !defined(CONFIG_USBD_MONITOR) && !defined(CONFIG_USBD_MONITOR_MODULE)
	dbg_pm (0, "pm_dev->callback#%p", pm_dev->callback);
	if (!udc_connected ()) {
		/* Fake a call from the PM system to suspend the UDC until it
		   is needed (cable connect, etc) */
		(void) bi_pm_event (pm_dev, PM_SUSPEND, NULL);
		/* There appears to be no constant for this, but inspection
		   of arch/arm/mach-l7200/apm.c:send_event() shows that the
		   suspended state is 3 (i.e. pm_send_all(PM_SUSPEND, (void *)3))
		   corresponding to ACPI_D3. */
		pm_dev->state = 3;
	}
#endif
	if (dbgflg_usbdbi_tick > 0) {
		// start ticker
		ticker_kickoff ();
	}

#ifdef CONFIG_USBD_PROCFS
	{
		struct proc_dir_entry *p;

		// create proc filesystem entries
		if ((p = create_proc_entry ("usbd", 0, 0)) == NULL) {
			return -ENOMEM;
		}
		p->proc_fops = &usbd_proc_operations_functions;
	}
#endif
	dbgLEAVE (dbgflg_usbdbi_init, 1);
	return 0;
}
Example #4
0
/* bi_config - commission bus interface driver
 */
static int bi_config(struct usb_device_instance *device)
{
    int i;

    struct usb_interface_descriptor *interface;
    struct usb_endpoint_descriptor *endpoint_descriptor;

    int found_tx = 0;
    int found_rx = 0;

    dbg_init(1,"checking config: config: %d interface: %d alternate: %d",
            device->configuration, device->interface, device->alternate);

    bi_disable_endpoints(device);

    // audit configuration for compatibility
    if (!(interface = usbd_device_interface_descriptor(device,
                    0, device->configuration, device->interface, device->alternate)))
    {
        dbg_init(0,"cannot fetch interface descriptor c:%d i:%d a:%d",
                 device->configuration, device->interface, device->alternate);
        return -EINVAL;
    }


    dbg_init(2, "endpoints: %d", interface->bNumEndpoints);

    // iterate across all endpoints for this configuration and verify they are valid
    for (i = 0; i < interface->bNumEndpoints; i++) {
        int transfersize;

        int physical_endpoint;
        int logical_endpoint;

        //dbg_init(0, "fetching endpoint %d", i);
        if (!(endpoint_descriptor = usbd_device_endpoint_descriptor_index(device, 0,
                device->configuration, device->interface, device->alternate, i)))
        {
            dbg_init(0, "cannot fetch endpoint descriptor: %d", i);
            continue;
        }

        // XXX check this
        transfersize = usbd_device_endpoint_transfersize(device, 0,
                device->configuration, device->interface, device->alternate, i);



        logical_endpoint = endpoint_descriptor->bEndpointAddress;

        if (!(physical_endpoint = udc_check_ep(logical_endpoint,
                                               endpoint_descriptor->wMaxPacketSize,
                                               device))) {
            dbg_init(2, "endpoint[%d]: l: %02x p: %02x transferSize: %d packetSize: %02x INVALID",
                    i, logical_endpoint, physical_endpoint,
                    transfersize, endpoint_descriptor->wMaxPacketSize);

            dbg_init(2, "invalid endpoint: %d %d", logical_endpoint, physical_endpoint);
            return -EINVAL;
        }
        else {
            struct usb_endpoint_instance *endpoint = device->bus->endpoint_array + physical_endpoint;

            dbg_init(2, "endpoint[%d]: l: %02x p: %02x transferSize: %d packetSize: %02x FOUND",
                     i, logical_endpoint, physical_endpoint,
                     transfersize, endpoint_descriptor->wMaxPacketSize);

            dbg_init(2,"epd->bEndpointAddress=%d",
                     endpoint_descriptor->bEndpointAddress);
            endpoint->endpoint_address = endpoint_descriptor->bEndpointAddress;

            if (endpoint_descriptor->wMaxPacketSize > 64) {
                dbg_init(0,"incompatible with endpoint size: %x",
                        endpoint_descriptor->wMaxPacketSize);
                return -EINVAL;
            }

            if (endpoint_descriptor->bEndpointAddress & IN) {
                found_tx++;
                endpoint->tx_attributes = endpoint_descriptor->bmAttributes;
                endpoint->tx_transferSize = transfersize&0xfff;
                endpoint->tx_packetSize = endpoint_descriptor->wMaxPacketSize;
                endpoint->last = 0;
                endpoint->tx_urb = NULL;
            }
            else {
                found_rx++;
                endpoint->rcv_attributes = endpoint_descriptor->bmAttributes;
                endpoint->rcv_transferSize = transfersize&0xfff;
                endpoint->rcv_packetSize = endpoint_descriptor->wMaxPacketSize;
                endpoint->rcv_urb = NULL;
            }
        }
    }

    if (device->status == USBD_OK) {
        for (i = 1; i < device->bus->driver->max_endpoints; i++) {

            struct usb_endpoint_instance *endpoint = device->bus->endpoint_array + i;

            // udc_setup_ep(device, i, endpoint->endpoint_address?  endpoint : NULL);
            udc_setup_ep(device, i, endpoint);
        }
    }

    return 0;
}
Example #5
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);
}