static int ehci_hsic_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct hc_driver *driver; struct usb_hcd *hcd; struct ehci_hcd *ehci; int irq, retval; pr_debug("initializing Intel EHCI HSIC Host Controller\n"); if (usb_disabled()) return -ENODEV; if (!id) return -EINVAL; pci_dev = pdev; if (pci_enable_device(pdev) < 0) return -ENODEV; pdev->current_state = PCI_D0; wake_lock_init(&hsic.resume_wake_lock, WAKE_LOCK_SUSPEND, "hsic_aux2_wlock"); wake_lock_init(&hsic.s3_wake_lock, WAKE_LOCK_SUSPEND, "hsic_s3_wlock"); hsic.hsic_pm_nb.notifier_call = hsic_pm_notify; usb_register_notify(&hsic.hsic_pm_nb); hsic.hsic_s3_entry_nb.notifier_call = hsic_s3_entry_notify; register_pm_notifier(&hsic.hsic_s3_entry_nb); /* we need not call pci_enable_dev since otg transceiver already take * the control of this device and this probe actaully gets called by * otg transceiver driver with HNP protocol. */ irq = pdev->irq; if (!pdev->irq) { dev_dbg(&pdev->dev, "No IRQ.\n"); retval = -ENODEV; goto disable_pci; } driver = (struct hc_driver *)id->driver_data; if (!driver) return -EINVAL; /* AUX GPIO init */ retval = hsic_aux_gpio_init(); if (retval < 0) { dev_err(&pdev->dev, "AUX GPIO init fail\n"); retval = -ENODEV; goto disable_pci; } /* AUX GPIO init */ retval = hsic_wakeup_gpio_init(); if (retval < 0) { dev_err(&pdev->dev, "Wakeup GPIO init fail\n"); retval = -ENODEV; goto disable_pci; } hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { retval = -ENOMEM; goto disable_pci; } ehci = hcd_to_ehci(hcd); hcd->rsrc_start = pci_resource_start(pdev, 0); hcd->rsrc_len = pci_resource_len(pdev, 0); if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, driver->description)) { dev_dbg(&pdev->dev, "controller already in use\n"); retval = -EBUSY; goto clear_companion; } hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); if (hcd->regs == NULL) { dev_dbg(&pdev->dev, "error mapping memory\n"); retval = -EFAULT; goto release_mem_region; } pci_set_master(pdev); if (hsic.hsic_enable_created == 0) { retval = create_device_files(); if (retval < 0) { dev_dbg(&pdev->dev, "error create device files\n"); goto release_mem_region; } hsic.hsic_enable_created = 1; } if (hsic.hsic_mutex_init == 0) { mutex_init(&hsic.hsic_mutex); mutex_init(&hsic.wlock_mutex); hsic.hsic_mutex_init = 1; } if (hsic.aux_wq_init == 0) { init_waitqueue_head(&hsic.aux_wq); hsic.aux_wq_init = 1; } hsic.work_queue = create_singlethread_workqueue("hsic"); INIT_DELAYED_WORK(&hsic.wakeup_work, wakeup_work); INIT_DELAYED_WORK(&(hsic.hsic_aux), hsic_aux_work); hcd->hsic_notify = hsic_notify; retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED | IRQF_NO_SUSPEND); if (retval != 0) goto unmap_registers; dev_set_drvdata(&pdev->dev, hcd); /* Clear phy low power mode, enable phy clock */ ehci_hsic_phy_power(ehci, 0); if (pci_dev_run_wake(pdev)) pm_runtime_put_noidle(&pdev->dev); if (!enabling_disabling) { /* Check here to avoid to call pm_runtime_put_noidle() twice */ if (!pci_dev_run_wake(pdev)) pm_runtime_put_noidle(&pdev->dev); pm_runtime_allow(&pdev->dev); } hsic.hsic_stopped = 0; hsic_enable = 1; hsic.s3_rt_state = RESUMED; s3_wake_lock(); hsic_debugfs_init(hcd); return retval; unmap_registers: destroy_workqueue(hsic.work_queue); if (driver->flags & HCD_MEMORY) { iounmap(hcd->regs); release_mem_region: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); } else release_region(hcd->rsrc_start, hcd->rsrc_len); clear_companion: dev_set_drvdata(&pdev->dev, NULL); usb_put_hcd(hcd); disable_pci: pci_disable_device(pdev); dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval); wake_lock_destroy(&(hsic.resume_wake_lock)); wake_lock_destroy(&hsic.s3_wake_lock); return retval; }
/* * We need to register our own PCI probe function (instead of the USB core's * function) in order to create a second roothub under xHCI. */ static int xhci_ush_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { int retval; struct xhci_hcd *xhci; struct hc_driver *driver; struct usb_hcd *hcd; driver = (struct hc_driver *)id->driver_data; pci_dev = dev; /* AUX GPIO init */ retval = hsic_aux_gpio_init(); if (retval < 0) { dev_err(&dev->dev, "AUX GPIO init fail\n"); retval = -ENODEV; } /* AUX GPIO init */ retval = hsic_wakeup_gpio_init(); if (retval < 0) { dev_err(&dev->dev, "Wakeup GPIO init fail\n"); retval = -ENODEV; } /* Register the USB 2.0 roothub. * FIXME: USB core must know to register the USB 2.0 roothub first. * This is sort of silly, because we could just set the HCD driver flags * to say USB 2.0, but I'm not sure what the implications would be in * the other parts of the HCD code. */ retval = usb_hcd_pci_probe(dev, id); if (retval) return retval; /* USB 2.0 roothub is stored in the PCI device now. */ hcd = dev_get_drvdata(&dev->dev); xhci = hcd_to_xhci(hcd); xhci->shared_hcd = usb_create_shared_hcd(driver, &dev->dev, pci_name(dev), hcd); if (!xhci->shared_hcd) { retval = -ENOMEM; goto dealloc_usb2_hcd; } /* Set the xHCI pointer before xhci_pci_setup() (aka hcd_driver.reset) * is called by usb_add_hcd(). */ *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; if (hsic.hsic_enable_created == 0) { retval = create_device_files(); if (retval < 0) { dev_dbg(&dev->dev, "error create device files\n"); goto dealloc_usb2_hcd; } hsic.hsic_enable_created = 1; } if (hsic.hsic_mutex_init == 0) { mutex_init(&hsic.hsic_mutex); hsic.hsic_mutex_init = 1; } if (hsic.aux_wq_init == 0) { init_waitqueue_head(&hsic.aux_wq); hsic.aux_wq_init = 1; } hsic.work_queue = create_singlethread_workqueue("hsic"); INIT_WORK(&hsic.wakeup_work, wakeup_work); INIT_DELAYED_WORK(&(hsic.hsic_aux), hsic_aux_work); retval = usb_add_hcd(xhci->shared_hcd, dev->irq, IRQF_SHARED); if (retval) goto put_usb3_hcd; /* Roothub already marked as USB 3.0 speed */ /* Enable Controller wakeup capability */ device_set_wakeup_enable(&dev->dev, true); /* Enable runtime pm ability */ hcd->rpm_control = 1; hcd->rpm_resume = 0; pm_runtime_set_active(&dev->dev); /* Check here to avoid to call pm_runtime_put_noidle() twice */ if (!pci_dev_run_wake(dev)) pm_runtime_put_noidle(&dev->dev); pm_runtime_allow(&dev->dev); hsic.hsic_stopped = 0; hsic_enable = 1; return 0; put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); dealloc_usb2_hcd: usb_hcd_pci_remove(dev); return retval; }