Exemplo n.º 1
0
/** Initialize hcd_t structure.
 * Initializes device and endpoint managers. Sets data and hook pointer to NULL.
 *
 * @param hcd hcd_t structure to initialize, non-null.
 * @param max_speed Maximum supported USB speed (full, high).
 * @param bandwidth Available bandwidth, passed to endpoint manager.
 * @param bw_count Bandwidth compute function, passed to endpoint manager.
 */
void hcd_init(hcd_t *hcd, usb_speed_t max_speed, size_t bandwidth,
    bw_count_func_t bw_count)
{
	assert(hcd);
	usb_bus_init(&hcd->bus, bandwidth, bw_count, max_speed);

	hcd_set_implementation(hcd, NULL, NULL);
}
Exemplo n.º 2
0
/**
 * usb_hcd_pci_probe - initialize PCI-based HCDs
 * @dev: USB Host Controller being probed
 * @id: pci hotplug id connecting controller to HCD framework
 * Context: !in_interrupt()
 *
 * Allocates basic PCI resources for this USB host controller, and
 * then invokes the start() method for the HCD associated with it
 * through the hotplug entry's driver_data.
 *
 * Store this function in the HCD's struct pci_driver as probe().
 */
int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
{
    struct hc_driver	*driver;
    unsigned long		resource, len;
    void __iomem		*base;
    struct usb_hcd		*hcd;
    int			retval, region;
    char			buf [8], *bufp = buf;

    if (usb_disabled())
        return -ENODEV;

    if (!id || !(driver = (struct hc_driver *) id->driver_data))
        return -EINVAL;

    if (pci_enable_device (dev) < 0)
        return -ENODEV;
    dev->current_state = 0;
    dev->dev.power.power_state = 0;

    if (!dev->irq) {
        dev_err (&dev->dev,
                 "Found HC with no IRQ.  Check BIOS/PCI %s setup!\n",
                 pci_name(dev));
        retval = -ENODEV;
        goto done;
    }

    if (driver->flags & HCD_MEMORY) {	// EHCI, OHCI
        region = 0;
        resource = pci_resource_start (dev, 0);
        len = pci_resource_len (dev, 0);
        if (!request_mem_region (resource, len, driver->description)) {
            dev_dbg (&dev->dev, "controller already in use\n");
            retval = -EBUSY;
            goto done;
        }
        base = ioremap_nocache (resource, len);
        if (base == NULL) {
            dev_dbg (&dev->dev, "error mapping memory\n");
            retval = -EFAULT;
clean_1:
            release_mem_region (resource, len);
            dev_err (&dev->dev, "init %s fail, %d\n",
                     pci_name(dev), retval);
            goto done;
        }

    } else { 				// UHCI
        resource = len = 0;
        for (region = 0; region < PCI_ROM_RESOURCE; region++) {
            if (!(pci_resource_flags (dev, region) & IORESOURCE_IO))
                continue;

            resource = pci_resource_start (dev, region);
            len = pci_resource_len (dev, region);
            if (request_region (resource, len,
                                driver->description))
                break;
        }
        if (region == PCI_ROM_RESOURCE) {
            dev_dbg (&dev->dev, "no i/o regions available\n");
            retval = -EBUSY;
            goto done;
        }
        base = (void __iomem *) resource;
    }

    // driver->reset(), later on, will transfer device from
    // control by SMM/BIOS to control by Linux (if needed)

    hcd = driver->hcd_alloc ();
    if (hcd == NULL) {
        dev_dbg (&dev->dev, "hcd alloc fail\n");
        retval = -ENOMEM;
clean_2:
        if (driver->flags & HCD_MEMORY) {
            iounmap (base);
            goto clean_1;
        } else {
            release_region (resource, len);
            dev_err (&dev->dev, "init %s fail, %d\n",
                     pci_name(dev), retval);
            goto done;
        }
    }
    // hcd zeroed everything
    hcd->regs = base;
    hcd->region = region;

    pci_set_drvdata (dev, hcd);
    hcd->driver = driver;
    hcd->description = driver->description;
    hcd->self.bus_name = pci_name(dev);
#ifdef CONFIG_PCI_NAMES
    hcd->product_desc = dev->pretty_name;
#else
    if (hcd->product_desc == NULL)
        hcd->product_desc = "USB Host Controller";
#endif
    hcd->self.controller = &dev->dev;

    if ((retval = hcd_buffer_create (hcd)) != 0) {
clean_3:
        kfree (hcd);
        goto clean_2;
    }

    dev_info (hcd->self.controller, "%s\n", hcd->product_desc);

    /* till now HC has been in an indeterminate state ... */
    if (driver->reset && (retval = driver->reset (hcd)) < 0) {
        dev_err (hcd->self.controller, "can't reset\n");
        goto clean_3;
    }
    hcd->state = USB_STATE_HALT;

    pci_set_master (dev);
#ifndef __sparc__
    sprintf (buf, "%d", dev->irq);
#else
    bufp = __irq_itoa(dev->irq);
#endif
    retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ,
                          hcd->description, hcd);
    if (retval != 0) {
        dev_err (hcd->self.controller,
                 "request interrupt %s failed\n", bufp);
        goto clean_3;
    }
    hcd->irq = dev->irq;

    dev_info (hcd->self.controller, "irq %s, %s 0x%lx\n", bufp,
              (driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
              resource);

    usb_bus_init (&hcd->self);
    hcd->self.op = &usb_hcd_operations;
    hcd->self.release = &usb_hcd_release;
    hcd->self.hcpriv = (void *) hcd;
    init_timer (&hcd->rh_timer);

    INIT_LIST_HEAD (&hcd->dev_list);

    usb_register_bus (&hcd->self);

    if ((retval = driver->start (hcd)) < 0) {
        dev_err (hcd->self.controller, "init error %d\n", retval);
        usb_hcd_pci_remove (dev);
    }

done:
    if (retval != 0)
        pci_disable_device (dev);
    return retval;
}
Exemplo n.º 3
0
/**
 * usb_hcd_pxa27x_probe - initialize pxa27x-based HCDs
 * Context: !in_interrupt()
 *
 * Allocates basic resources for this USB host controller, and
 * then invokes the start() method for the HCD associated with it
 * through the hotplug entry's driver_data.
 *
 */
int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
			  struct usb_hcd **hcd_out,
			  struct platform_device *dev)
{
	int retval;
	struct usb_hcd *hcd = 0;

	unsigned int *addr = NULL;

	if (!request_mem_region(dev->resource[0].start,
				dev->resource[0].end
				- dev->resource[0].start + 1, hcd_name)) {
		pr_debug("request_mem_region failed");
		return -EBUSY;
	}

	pxa27x_start_hc(dev);

	/* Select Power Management Mode */
	pxa27x_ohci_select_pmm( PMM_PERPORT_MODE );

	/* If choosing PMM_PERPORT_MODE, we should set the port power before we use it. */
	if (pxa27x_ohci_set_port_power(1) < 0)
		printk(KERN_ERR "Setting port 1 power failed.\n");

	if (pxa27x_ohci_clear_port_power(2) < 0)
		printk(KERN_ERR "Setting port 2 power failed.\n");

	if (pxa27x_ohci_clear_port_power(3) < 0)
		printk(KERN_ERR "Setting port 3 power failed.\n");

	addr = ioremap(dev->resource[0].start,
		       dev->resource[0].end - dev->resource[0].start + 1);
	if (!addr) {
		pr_debug("ioremap failed");
		retval = -ENOMEM;
		goto err1;
	}

	hcd = driver->hcd_alloc ();
	if (hcd == NULL){
		pr_debug ("hcd_alloc failed");
		retval = -ENOMEM;
		goto err1;
	}

	if(dev->resource[1].flags != IORESOURCE_IRQ){
		pr_debug ("resource[1] is not IORESOURCE_IRQ");
		retval = -ENOMEM;
		goto err1;
	}

	hcd->driver = (struct hc_driver *) driver;
	hcd->description = driver->description;
	hcd->irq = dev->resource[1].start;
	hcd->regs = addr;
	hcd->self.controller = &dev->dev;

	retval = hcd_buffer_create (hcd);
	if (retval != 0) {
		pr_debug ("pool alloc fail");
		goto err1;
	}

	retval = request_irq (hcd->irq, usb_hcd_irq, SA_INTERRUPT,
			      hcd->description, hcd);
	if (retval != 0) {
		pr_debug("request_irq(%d) failed with retval %d\n",hcd->irq,retval);
		retval = -EBUSY;
		goto err2;
	}

	pr_debug ("%s (pxa27x) at 0x%p, irq %d",
	     hcd->description, hcd->regs, hcd->irq);

	usb_bus_init (&hcd->self);
	hcd->self.op = &usb_hcd_operations;
	hcd->self.hcpriv = (void *) hcd;
	hcd->self.bus_name = "pxa27x";
	hcd->product_desc = "PXA27x OHCI";

	INIT_LIST_HEAD (&hcd->dev_list);

	usb_register_bus (&hcd->self);

	if ((retval = driver->start (hcd)) < 0) {
		usb_hcd_pxa27x_remove(hcd, dev);
		return retval;
	}

	*hcd_out = hcd;
	return 0;

 err2:
	hcd_buffer_destroy (hcd);
	if (hcd)
		driver->hcd_free(hcd);
 err1:
	pxa27x_stop_hc(dev);
	release_mem_region(dev->resource[0].start,
				dev->resource[0].end
			   - dev->resource[0].start + 1);
	return retval;
}
Exemplo n.º 4
0
Arquivo: hcd-pci.c Projeto: kidoz/cxbx
/**
 * usb_hcd_pci_probe - initialize PCI-based HCDs
 * @dev: USB Host Controller being probed
 * @id: pci hotplug id connecting controller to HCD framework
 * Context: !in_interrupt()
 *
 * Allocates basic PCI resources for this USB host controller, and
 * then invokes the start() method for the HCD associated with it
 * through the hotplug entry's driver_data.
 *
 * Store this function in the HCD's struct pci_driver as probe().
 */
int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
{
	struct hc_driver	*driver;
	unsigned long		resource, len;
	void			*base;
	struct usb_hcd		*hcd;
	int			retval, region;
	char			buf [8], *bufp = buf;

	if (usb_disabled())
		return -ENODEV;

	if (!id || !(driver = (struct hc_driver *) id->driver_data))
		return -EINVAL;

	if (pci_enable_device (dev) < 0)
		return -ENODEV;

        if (!dev->irq) {
        	err ("Found HC with no IRQ.  Check BIOS/PCI %s setup!",
			dev->slot_name);
   	        return -ENODEV;
        }

	if (driver->flags & HCD_MEMORY) {	// EHCI, OHCI
		region = 0;
		resource = pci_resource_start (dev, 0);
		len = pci_resource_len (dev, 0);
		if (!request_mem_region (resource, len, driver->description)) {
			dbg ("controller already in use");
			return -EBUSY;
		}
		base = ioremap_nocache (resource, len);
		if (base == NULL) {
			dbg ("error mapping memory");
			retval = -EFAULT;
clean_1:
			release_mem_region (resource, len);
			err ("init %s fail, %d", dev->slot_name, retval);
			return retval;
		}

	} else { 				// UHCI
		resource = len = 0;
		for (region = 0; region < PCI_ROM_RESOURCE; region++) {
			if (!(pci_resource_flags (dev, region) & IORESOURCE_IO))
				continue;

			resource = pci_resource_start (dev, region);
			len = pci_resource_len (dev, region);
			if (request_region (resource, len,
					driver->description))
				break;
		}
		if (region == PCI_ROM_RESOURCE) {
			dbg ("no i/o regions available");
			return -EBUSY;
		}
		base = (void *) resource;
	}

	// driver->start(), later on, will transfer device from
	// control by SMM/BIOS to control by Linux (if needed)

	pci_set_master (dev);

	hcd = driver->hcd_alloc ();
	if (hcd == NULL){
		dbg ("hcd alloc fail");
		retval = -ENOMEM;
clean_2:
		if (driver->flags & HCD_MEMORY) {
			iounmap (base);
			goto clean_1;
		} else {
			release_region (resource, len);
			err ("init %s fail, %d", dev->slot_name, retval);
			return retval;
		}
	}
	pci_set_drvdata (dev, hcd);
	hcd->driver = driver;
	hcd->description = driver->description;
	hcd->pdev = dev;
	hcd->self.bus_name = dev->slot_name;
	hcd->product_desc = dev->dev.name;
	hcd->self.controller = &dev->dev;
	hcd->controller = hcd->self.controller;

	if ((retval = hcd_buffer_create (hcd)) != 0) {
clean_3:
		driver->hcd_free (hcd);
		goto clean_2;
	}

	dev_info (hcd->controller, "%s\n", hcd->product_desc);

#ifndef __sparc__
	sprintf (buf, "%d", dev->irq);
#else
	bufp = __irq_itoa(dev->irq);
#endif
	if (request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ, hcd->description, hcd)
			!= 0) {
		dev_err (hcd->controller,
				"request interrupt %s failed\n", bufp);
		retval = -EBUSY;
		goto clean_3;
	}
	hcd->irq = dev->irq;

	hcd->regs = base;
	hcd->region = region;
	dev_info (hcd->controller, "irq %s, %s %p\n", bufp,
		(driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
		base);

	usb_bus_init (&hcd->self);
	hcd->self.op = &usb_hcd_operations;
	hcd->self.hcpriv = (void *) hcd;

	INIT_LIST_HEAD (&hcd->dev_list);

	usb_register_bus (&hcd->self);

	if ((retval = driver->start (hcd)) < 0)
		usb_hcd_pci_remove (dev);

	return retval;
} 
Exemplo n.º 5
0
/**
 * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs
 * Context: !in_interrupt()
 *
 * Allocates basic resources for this USB host controller.
 *
 * Store this function in the HCD's struct pci_driver as probe().
 */
static int usb_hcd_ppc_soc_probe(struct hc_driver *driver,
			  struct platform_device *pdev)
{
	int retval;
	struct usb_hcd *hcd;
	struct ehci_hcd	*ehci;
	struct resource *res;
	unsigned long res_len;
	int irq;

	pr_debug("Initializing PPC-SOC EHCI USB Controller\n");

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res) {
		pr_debug(__FILE__ ": no irq\n");
		return -ENODEV;
	}
	irq = res->start;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		pr_debug(__FILE__ ": no reg addr\n");
		return -ENODEV;
	}
	hcd = driver->hcd_alloc();
	if (!hcd)
		return -ENOMEM;

	ehci = hcd_to_ehci(hcd);
	ehci->big_endian = 1;

	res_len = res->end - res->start + 1;
	if (!request_mem_region(res->start, res_len, hcd_name)) {
		pr_debug(__FILE__ ": request_mem_region failed\n");
		retval = -EBUSY;
		goto err1;
	}

	hcd->regs = ioremap64(res->start, res_len);
	if (!hcd->regs) {
		pr_debug(__FILE__ ": ioremap failed\n");
		retval = -ENOMEM;
		goto err2;
	}

	dev_set_drvdata(&pdev->dev, hcd);
	hcd->driver = driver;
	hcd->description = driver->description;
	hcd->self.bus_name = pdev->dev.bus_id;
	hcd->product_desc = "PPC-SOC EHCI USB";
	hcd->self.controller = &pdev->dev;

	if ((retval = hcd_buffer_create(hcd)) != 0) {
		pr_debug(__FILE__ ": hcd_buffer_create failed\n");
		retval = -ENOMEM;
		goto err3;
	}

	hcd->state = USB_STATE_HALT;

	retval = request_irq(irq, usb_hcd_irq, SA_SHIRQ,
				hcd->description, hcd);
	if (retval != 0) {
		pr_debug(__FILE__ ": request_irq failed\n");
		retval = -ENODEV;
		goto err4;
	}

	hcd->irq = irq;
	usb_bus_init(&hcd->self);
	hcd->self.op = &usb_hcd_operations;
	hcd->self.release = &usb_hcd_release;
	hcd->self.hcpriv = (void *) hcd;
	init_timer(&hcd->rh_timer);

	INIT_LIST_HEAD(&hcd->dev_list);

	usb_register_bus(&hcd->self);

	if ((retval = driver->start(hcd)) < 0) {
		dev_err(hcd->self.controller, "init error %d\n", retval);
		usb_hcd_ppc_soc_remove(pdev);
	}
	return retval;

err4:
	hcd_buffer_destroy(hcd);
err3:
	iounmap(hcd->regs);
err2:
	release_mem_region(res->start, res_len);
err1:
	kfree(hcd);
	return retval;
}
Exemplo n.º 6
0
/**
 * usb_hcd_omap_probe - initialize OMAP-based HCDs
 * Context: !in_interrupt()
 *
 * Allocates basic resources for this USB host controller, and
 * then invokes the start() method for the HCD associated with it
 * through the hotplug entry's driver_data.
 */
int usb_hcd_omap_probe (const struct hc_driver *driver,
			  struct platform_device *pdev)
{
	int retval;
	struct usb_hcd *hcd = 0;
	struct ohci_hcd *ohci;

	if (pdev->num_resources != 2) {
		printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", 
		       pdev->num_resources);
		return -ENODEV;
	}

	if (pdev->resource[0].flags != IORESOURCE_MEM 
	    || pdev->resource[1].flags != IORESOURCE_IRQ) {
		printk(KERN_ERR "hcd probe: invalid resource type\n");
		return -ENODEV;
	}

	if (!request_mem_region(pdev->resource[0].start, 
				pdev->resource[0].end - pdev->resource[0].start + 1, hcd_name)) {
		dev_dbg(&pdev->dev, "request_mem_region failed\n");
		return -EBUSY;
	}

	hcd = driver->hcd_alloc ();
	if (hcd == NULL){
		dev_dbg(&pdev->dev, "hcd_alloc failed\n");
		retval = -ENOMEM;
		goto err1;
	}
	dev_set_drvdata(&pdev->dev, hcd);
	ohci = hcd_to_ohci(hcd);

	hcd->driver = (struct hc_driver *) driver;
	hcd->description = driver->description;
	hcd->irq = pdev->resource[1].start;
	hcd->regs = (void *)pdev->resource[0].start;
	hcd->self.controller = &pdev->dev;

	retval = omap_start_hc(ohci, pdev);
	if (retval < 0)
		goto err1;

	retval = hcd_buffer_create (hcd);
	if (retval != 0) {
		dev_dbg(&pdev->dev, "pool alloc fail\n");
		goto err1;
	}

	retval = request_irq (hcd->irq, usb_hcd_irq, 
#ifdef CONFIG_PREEMPT_HARDIRQS
			      0, hcd->description, hcd);
#else
			      SA_INTERRUPT, hcd->description, hcd);
#endif
	if (retval != 0) {
		dev_dbg(&pdev->dev, "request_irq failed\n");
		retval = -EBUSY;
		goto err2;
	}

	dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);

	usb_bus_init (&hcd->self);
	hcd->self.op = &usb_hcd_operations;
	hcd->self.release = &usb_hcd_release;
	hcd->self.hcpriv = (void *) hcd;
	hcd->self.bus_name = pdev->dev.bus_id;
	hcd->product_desc = "OMAP OHCI";

	INIT_LIST_HEAD (&hcd->dev_list);
	usb_register_bus (&hcd->self);

	if ((retval = driver->start (hcd)) < 0) 
	{
		usb_hcd_omap_remove(hcd, pdev);
		return retval;
	}

	return 0;

 err2:
	hcd_buffer_destroy (hcd);
 err1:
	kfree(hcd);
	omap_stop_hc(pdev);

	release_mem_region(pdev->resource[0].start, 
			   pdev->resource[0].end - pdev->resource[0].start + 1);

	dev_set_drvdata(&pdev->dev, 0);
	return retval;
}
/**
 * usb_hcd_omap_probe - initialize OMAP-based HCDs
 * Context: !in_interrupt()
 *
 * Allocates basic resources for this USB host controller, and
 * then invokes the start() method for the HCD associated with it
 * through the hotplug entry's driver_data.
 *
 * Store this function in the HCD's struct pci_driver as probe().
 */
int usb_hcd_omap_probe (const struct hc_driver *driver,
			  struct usb_hcd **hcd_out,
			  struct omap_dev *dev)
{
	int retval;
	struct usb_hcd *hcd = 0;

	if (!request_mem_region(dev->res.start, 
				dev->res.end - dev->res.start + 1, hcd_name)) {
		dbg("request_mem_region failed");
		return -EBUSY;
	}

	omap_start_hc(dev);

	hcd = driver->hcd_alloc ();
	if (hcd == NULL){
		dbg ("hcd_alloc failed");
		retval = -ENOMEM;
		goto err1;
	}

	hcd->driver = (struct hc_driver *) driver;
	hcd->description = driver->description;
	hcd->irq = dev->irq[0];
	hcd->regs = dev->mapbase;
	hcd->self.controller = &dev->dev;

	retval = hcd_buffer_create (hcd);
	if (retval != 0) {
		dbg ("pool alloc fail");
		goto err1;
	}

	retval = request_irq (hcd->irq, 
			      usb_hcd_omap_hcim_irq, 
			      SA_INTERRUPT, hcd->description, hcd);
	if (retval != 0) {
		dbg("request_irq failed");
		retval = -EBUSY;
		goto err2;
	}

	info ("%s (OMAP) at 0x%p, irq %d\n",
	      hcd->description, hcd->regs, hcd->irq);

	usb_bus_init (&hcd->self);
	hcd->self.op = &usb_hcd_operations;
	hcd->self.hcpriv = (void *) hcd;
	hcd->self.bus_name = "omap";
	hcd->product_desc = "OMAP OHCI";

	INIT_LIST_HEAD (&hcd->dev_list);
	usb_register_bus (&hcd->self);

	if ((retval = driver->start (hcd)) < 0) 
	{
		usb_hcd_omap_remove(hcd, dev);
		return retval;
	}

	*hcd_out = hcd;
	return 0;

 err2:
	hcd_buffer_destroy (hcd);
	if (hcd)
		driver->hcd_free(hcd);
 err1:
	omap_stop_hc(dev);

	release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);

	return retval;
}
Exemplo n.º 8
0
/**
 * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs
 * Context: !in_interrupt()
 *
 * Allocates basic resources for this USB host controller.
 *
 * Store this function in the HCD's struct pci_driver as probe().
 */
static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
			  struct usb_hcd **hcd_out,
			  struct platform_device *pdev)
{
	int retval;
	struct usb_hcd *hcd = 0;
	struct ohci_hcd	*ohci;
	struct resource *res;
	int irq;

	pr_debug("initializing PPC-SOC USB Controller\n");

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res) {
		pr_debug(__FILE__ ": no irq\n");
		return -ENODEV;
	}
	irq = res->start;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		pr_debug(__FILE__ ": no reg addr\n");
		return -ENODEV;
	}
	if (!request_mem_region(res->start, res->end - res->start + 1,
					hcd_name)) {
		pr_debug(__FILE__ ": request_mem_region failed\n");
		return -EBUSY;
	}

	hcd = driver->hcd_alloc ();
	if (!hcd){
		pr_debug(__FILE__ ": hcd_alloc failed\n");
		retval = -ENOMEM;
		goto err1;
	}

	ohci = hcd_to_ohci(hcd);

	ohci->flags |= OHCI_BIG_ENDIAN;

	hcd->driver = (struct hc_driver *) driver;
	hcd->description = driver->description;
	hcd->irq = irq;
	hcd->regs = (struct ohci_regs *) ioremap(res->start,
						res->end - res->start + 1);
	if (!hcd->regs) {
		pr_debug(__FILE__ ": ioremap failed\n");
		retval = -ENOMEM;
		goto err2;
	}

	hcd->self.controller = &pdev->dev;

	retval = hcd_buffer_create(hcd);
	if (retval) {
		pr_debug(__FILE__ ": pool alloc fail\n");
		goto err3;
	}

	retval = request_irq(hcd->irq, usb_hcd_irq, SA_INTERRUPT,
				hcd_name, hcd);
	if (retval) {
		pr_debug(__FILE__ ": request_irq failed, returned %d\n",
								retval);
		retval = -EBUSY;
		goto err4;
	}

	info("%s (PPC-SOC) at 0x%p, irq %d\n",
	      hcd_name, hcd->regs, hcd->irq);

	usb_bus_init(&hcd->self);
	hcd->self.op = &usb_hcd_operations;
	hcd->self.release = & usb_hcd_release;
	hcd->self.hcpriv = (void *) hcd;
	hcd->self.bus_name = "PPC-SOC USB";
	hcd->product_desc = "PPC-SOC OHCI";

	INIT_LIST_HEAD(&hcd->dev_list);

	usb_register_bus(&hcd->self);

	if ((retval = driver->start(hcd)) < 0) {
		usb_hcd_ppc_soc_remove(hcd, pdev);
		return retval;
	}

	*hcd_out = hcd;
	return 0;

 err4:
	hcd_buffer_destroy(hcd);
 err3:
	iounmap(hcd->regs);
 err2:
	dev_set_drvdata(&pdev->dev, NULL);
 err1:
	pr_debug("Removing PPC-SOC USB Controller\n");
	release_mem_region(res->start, res->end - res->start + 1);
	return retval;
}