/** 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); }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }