static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd); struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data; if (pdata && pdata->swfi_latency) pm_qos_remove_request(&mehci->pm_qos_req_dma); if (mehci->peripheral_status_irq) free_irq(mehci->peripheral_status_irq, mehci); if (mehci->wakeup_irq) { if (mehci->wakeup_irq_enabled) disable_irq_wake(mehci->wakeup_irq); free_irq(mehci->wakeup_irq, mehci); } /* * If the update request is called after unregister, the request will * fail. Results are undefined if unregister is called in the middle of * update request. */ mehci->bus_vote = false; cancel_work_sync(&mehci->bus_vote_w); if (mehci->bus_perf_client) msm_bus_scale_unregister_client(mehci->bus_perf_client); ehci_hsic_msm_debugfs_cleanup(); device_init_wakeup(&pdev->dev, 0); pm_runtime_set_suspended(&pdev->dev); destroy_workqueue(ehci_wq); usb_remove_hcd(hcd); msm_hsic_config_gpios(mehci, 0); msm_hsic_init_vddcx(mehci, 0); msm_hsic_init_clocks(mehci, 0); wake_lock_destroy(&mehci->wlock); iounmap(hcd->regs); usb_put_hcd(hcd); return 0; }
static int __devexit ehci_hsic_msm_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd); struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data; if (pdata && pdata->swfi_latency) pm_qos_remove_request(&mehci->pm_qos_req_dma); if (mehci->peripheral_status_irq) free_irq(mehci->peripheral_status_irq, mehci); if (mehci->wakeup_irq) { if (mehci->wakeup_irq_enabled) disable_irq_wake(mehci->wakeup_irq); free_irq(mehci->wakeup_irq, mehci); } if (mehci->bus_perf_client) msm_bus_scale_unregister_client(mehci->bus_perf_client); ehci_hsic_msm_debugfs_cleanup(); device_init_wakeup(&pdev->dev, 0); pm_runtime_set_suspended(&pdev->dev); usb_remove_hcd(hcd); msm_hsic_config_gpios(mehci, 0); msm_hsic_init_vddcx(mehci, 0); msm_hsic_init_clocks(mehci, 0); wake_lock_destroy(&mehci->wlock); iounmap(hcd->regs); usb_put_hcd(hcd); return 0; }
static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev) { struct usb_hcd *hcd; struct resource *res; struct msm_hsic_hcd *mehci; struct msm_hsic_host_platform_data *pdata; int ret; dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n"); /* After parent device's probe is executed, it will be put in suspend * mode. When child device's probe is called, driver core is not * resuming parent device due to which parent will be in suspend even * though child is active. Hence resume the parent device explicitly. */ if (pdev->dev.parent) pm_runtime_get_sync(pdev->dev.parent); hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { dev_err(&pdev->dev, "Unable to create HCD\n"); return -ENOMEM; } hcd_to_bus(hcd)->skip_resume = true; hcd->irq = platform_get_irq(pdev, 0); if (hcd->irq < 0) { dev_err(&pdev->dev, "Unable to get IRQ resource\n"); ret = hcd->irq; goto put_hcd; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "Unable to get memory resource\n"); ret = -ENODEV; goto put_hcd; } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENOMEM; goto put_hcd; } mehci = hcd_to_hsic(hcd); mehci->dev = &pdev->dev; pdata = mehci->dev->platform_data; mehci->ehci.susp_sof_bug = 1; mehci->ehci.reset_sof_bug = 1; mehci->ehci.resume_sof_bug = 1; if (pdata) mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh; res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "peripheral_status_irq"); if (res) mehci->peripheral_status_irq = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_IO, "wakeup"); if (res) { mehci->wakeup_gpio = res->start; mehci->wakeup_irq = MSM_GPIO_TO_INT(res->start); dev_dbg(mehci->dev, "wakeup_irq: %d\n", mehci->wakeup_irq); } ret = msm_hsic_init_clocks(mehci, 1); if (ret) { dev_err(&pdev->dev, "unable to initialize clocks\n"); ret = -ENODEV; goto unmap; } ret = msm_hsic_init_vddcx(mehci, 1); if (ret) { dev_err(&pdev->dev, "unable to initialize VDDCX\n"); ret = -ENODEV; goto deinit_clocks; } init_completion(&mehci->rt_completion); init_completion(&mehci->gpt0_completion); ret = msm_hsic_reset(mehci); if (ret) { dev_err(&pdev->dev, "unable to initialize PHY\n"); goto deinit_vddcx; } ehci_wq = create_singlethread_workqueue("ehci_wq"); if (!ehci_wq) { dev_err(&pdev->dev, "unable to create workqueue\n"); ret = -ENOMEM; goto deinit_vddcx; } INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w); ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); if (ret) { dev_err(&pdev->dev, "unable to register HCD\n"); goto unconfig_gpio; } device_init_wakeup(&pdev->dev, 1); wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev)); wake_lock(&mehci->wlock); if (mehci->peripheral_status_irq) { ret = request_threaded_irq(mehci->peripheral_status_irq, NULL, hsic_peripheral_status_change, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_SHARED, "hsic_peripheral_status", mehci); if (ret) dev_err(&pdev->dev, "%s:request_irq:%d failed:%d", __func__, mehci->peripheral_status_irq, ret); } /* configure wakeup irq */ if (mehci->wakeup_irq) { ret = request_irq(mehci->wakeup_irq, msm_hsic_wakeup_irq, IRQF_TRIGGER_HIGH, "msm_hsic_wakeup", mehci); if (!ret) { disable_irq_nosync(mehci->wakeup_irq); } else { dev_err(&pdev->dev, "request_irq(%d) failed: %d\n", mehci->wakeup_irq, ret); mehci->wakeup_irq = 0; } } ret = ehci_hsic_msm_debugfs_init(mehci); if (ret) dev_dbg(&pdev->dev, "mode debugfs file is" "not available\n"); if (pdata && pdata->bus_scale_table) { mehci->bus_perf_client = msm_bus_scale_register_client(pdata->bus_scale_table); /* Configure BUS performance parameters for MAX bandwidth */ if (mehci->bus_perf_client) { mehci->bus_vote = true; queue_work(ehci_wq, &mehci->bus_vote_w); } else { dev_err(&pdev->dev, "%s: Failed to register BUS " "scaling client!!\n", __func__); } } __mehci = mehci; /* * This pdev->dev is assigned parent of root-hub by USB core, * hence, runtime framework automatically calls this driver's * runtime APIs based on root-hub's state. */ pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); /* Decrement the parent device's counter after probe. * As child is active, parent will not be put into * suspend mode. */ if (pdev->dev.parent) pm_runtime_put_sync(pdev->dev.parent); return 0; unconfig_gpio: destroy_workqueue(ehci_wq); msm_hsic_config_gpios(mehci, 0); deinit_vddcx: msm_hsic_init_vddcx(mehci, 0); deinit_clocks: msm_hsic_init_clocks(mehci, 0); unmap: iounmap(hcd->regs); put_hcd: usb_put_hcd(hcd); return ret; }