static int xhci_plat_probe(struct platform_device *pdev) { const struct hc_driver *driver; struct xhci_hcd *xhci; struct resource *res; struct usb_hcd *hcd; int ret; int irq; if (usb_disabled()) return -ENODEV; driver = &xhci_plat_xhci_driver; irq = platform_get_irq(pdev, 0); if (irq < 0) return -ENODEV; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) return -ENOMEM; hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, driver->description)) { dev_dbg(&pdev->dev, "controller already in use\n"); ret = -EBUSY; goto put_hcd; } hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_dbg(&pdev->dev, "error mapping memory\n"); ret = -EFAULT; goto release_mem_region; } ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto unmap_registers; /* USB 2.0 roothub is stored in the platform_device now. */ hcd = dev_get_drvdata(&pdev->dev); xhci = hcd_to_xhci(hcd); xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev, dev_name(&pdev->dev), hcd); if (!xhci->shared_hcd) { ret = -ENOMEM; goto dealloc_usb2_hcd; } /* * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset) * is called by usb_add_hcd(). */ *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto put_usb3_hcd; phy = usb_get_transceiver(); if (phy && phy->otg) { dev_dbg(&pdev->dev, "%s otg support available\n", __func__); hcd->driver->stop(hcd); ret = otg_set_host(phy->otg, &hcd->self); if (ret) { dev_err(&pdev->dev, "%s otg_set_host failed\n", __func__); usb_put_transceiver(phy); goto put_usb3_hcd; } } else { pm_runtime_no_callbacks(&pdev->dev); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); pm_runtime_get(&pdev->dev); } return 0; put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); dealloc_usb2_hcd: usb_remove_hcd(hcd); unmap_registers: iounmap(hcd->regs); release_mem_region: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); put_hcd: usb_put_hcd(hcd); return ret; }
static int mxhci_hsic_probe(struct platform_device *pdev) { struct hc_driver *driver; struct device_node *node = pdev->dev.of_node; struct mxhci_hsic_hcd *mxhci; struct xhci_hcd *xhci; struct resource *res; struct usb_hcd *hcd; unsigned int reg; int ret; int irq; u32 tmp[3]; if (usb_disabled()) return -ENODEV; driver = &mxhci_hsic_hc_driver; pdev->dev.dma_mask = &dma_mask; /* dbg log event settings */ dbg_hsic.log_events = enable_dbg_log; dbg_hsic.log_payload = enable_payload_log; dbg_hsic.inep_log_mask = ep_addr_rxdbg_mask; dbg_hsic.outep_log_mask = ep_addr_rxdbg_mask; /* usb2.0 root hub */ driver->hcd_priv_size = sizeof(struct mxhci_hsic_hcd); hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) return -ENOMEM; irq = platform_get_irq(pdev, 0); if (irq < 0) { ret = -ENODEV; goto put_hcd; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { ret = -ENODEV; goto put_hcd; } hcd_to_bus(hcd)->skip_resume = true; hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); hcd->regs = devm_request_and_ioremap(&pdev->dev, res); if (!hcd->regs) { dev_err(&pdev->dev, "error mapping memory\n"); ret = -EFAULT; goto put_hcd; } mxhci = hcd_to_hsic(hcd); mxhci->dev = &pdev->dev; mxhci->strobe = of_get_named_gpio(node, "hsic,strobe-gpio", 0); if (mxhci->strobe < 0) { ret = -EINVAL; goto put_hcd; } mxhci->data = of_get_named_gpio(node, "hsic,data-gpio", 0); if (mxhci->data < 0) { ret = -EINVAL; goto put_hcd; } ret = of_property_read_u32_array(node, "qcom,vdd-voltage-level", tmp, ARRAY_SIZE(tmp)); if (!ret) { mxhci->vdd_no_vol_level = tmp[0]; mxhci->vdd_low_vol_level = tmp[1]; mxhci->vdd_high_vol_level = tmp[2]; } else { dev_err(&pdev->dev, "failed to read qcom,vdd-voltage-level property\n"); ret = -EINVAL; goto put_hcd; } ret = mxhci_msm_config_gdsc(mxhci, 1); if (ret) { dev_err(&pdev->dev, "unable to configure hsic gdsc\n"); goto put_hcd; } ret = mxhci_hsic_init_clocks(mxhci, 1); if (ret) { dev_err(&pdev->dev, "unable to initialize clocks\n"); goto put_hcd; } ret = mxhci_hsic_init_vddcx(mxhci, 1); if (ret) { dev_err(&pdev->dev, "unable to initialize vddcx\n"); goto deinit_clocks; } mxhci_hsic_reset(mxhci); /* HSIC phy caliberation:set periodic caliberation interval ~2.048sec */ mxhci_hsic_ulpi_write(mxhci, 0xFF, MSM_HSIC_IO_CAL_PER); /* Enable periodic IO calibration in HSIC_CFG register */ mxhci_hsic_ulpi_write(mxhci, 0xA8, MSM_HSIC_CFG); /* Configure Strobe and Data GPIOs to enable HSIC */ ret = mxhci_hsic_config_gpios(mxhci); if (ret) { dev_err(mxhci->dev, " gpio configuarion failed\n"); goto deinit_vddcx; } /* enable STROBE_PAD_CTL */ reg = readl_relaxed(TLMM_GPIO_HSIC_STROBE_PAD_CTL); writel_relaxed(reg | 0x2000000, TLMM_GPIO_HSIC_STROBE_PAD_CTL); /* enable DATA_PAD_CTL */ reg = readl_relaxed(TLMM_GPIO_HSIC_DATA_PAD_CTL); writel_relaxed(reg | 0x2000000, TLMM_GPIO_HSIC_DATA_PAD_CTL); mb(); /* Enable LPM in Sleep mode and suspend mode */ reg = readl_relaxed(MSM_HSIC_CTRL_REG); reg |= CTRLREG_PLL_CTRL_SLEEP | CTRLREG_PLL_CTRL_SUSP; writel_relaxed(reg, MSM_HSIC_CTRL_REG); if (of_property_read_bool(node, "qti,disable-hw-clk-gating")) { reg = readl_relaxed(MSM_HSIC_GCTL); writel_relaxed((reg | GCTL_DSBLCLKGTNG), MSM_HSIC_GCTL); } /* enable pwr event irq for LPM_IN_L2_IRQ */ writel_relaxed(LPM_IN_L2_IRQ_MASK, MSM_HSIC_PWR_EVNT_IRQ_MASK); mxhci->wakeup_irq = platform_get_irq_byname(pdev, "wakeup_irq"); if (mxhci->wakeup_irq < 0) { mxhci->wakeup_irq = 0; dev_err(&pdev->dev, "failed to init wakeup_irq\n"); } else { /* enable wakeup irq only when entering lpm */ irq_set_status_flags(mxhci->wakeup_irq, IRQ_NOAUTOEN); ret = devm_request_irq(&pdev->dev, mxhci->wakeup_irq, mxhci_hsic_wakeup_irq, 0, "mxhci_hsic_wakeup", mxhci); if (ret) { dev_err(&pdev->dev, "request irq failed (wakeup irq)\n"); goto deinit_vddcx; } } ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto deinit_vddcx; hcd = dev_get_drvdata(&pdev->dev); xhci = hcd_to_xhci(hcd); /* USB 3.0 roothub */ /* no need for another instance of mxhci */ driver->hcd_priv_size = sizeof(struct xhci_hcd *); xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev, dev_name(&pdev->dev), hcd); if (!xhci->shared_hcd) { ret = -ENOMEM; goto remove_usb2_hcd; } hcd_to_bus(xhci->shared_hcd)->skip_resume = true; /* * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset) * is called by usb_add_hcd(). */ *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto put_usb3_hcd; spin_lock_init(&mxhci->wakeup_lock); mxhci->pwr_event_irq = platform_get_irq_byname(pdev, "pwr_event_irq"); if (mxhci->pwr_event_irq < 0) { dev_err(&pdev->dev, "platform_get_irq for pwr_event_irq failed\n"); goto remove_usb3_hcd; } ret = devm_request_irq(&pdev->dev, mxhci->pwr_event_irq, mxhci_hsic_pwr_event_irq, 0, "mxhci_hsic_pwr_evt", mxhci); if (ret) { dev_err(&pdev->dev, "request irq failed (pwr event irq)\n"); goto remove_usb3_hcd; } init_completion(&mxhci->phy_in_lpm); mxhci->wq = create_singlethread_workqueue("mxhci_wq"); if (!mxhci->wq) { dev_err(&pdev->dev, "unable to create workqueue\n"); ret = -ENOMEM; goto remove_usb3_hcd; } INIT_WORK(&mxhci->bus_vote_w, mxhci_hsic_bus_vote_w); mxhci->bus_scale_table = msm_bus_cl_get_pdata(pdev); if (!mxhci->bus_scale_table) { dev_dbg(&pdev->dev, "bus scaling is disabled\n"); } else { mxhci->bus_perf_client = msm_bus_scale_register_client(mxhci->bus_scale_table); /* Configure BUS performance parameters for MAX bandwidth */ if (mxhci->bus_perf_client) { mxhci->bus_vote = true; queue_work(mxhci->wq, &mxhci->bus_vote_w); } else { dev_err(&pdev->dev, "%s: bus scaling client reg err\n", __func__); ret = -ENODEV; goto delete_wq; } } ret = device_create_file(&pdev->dev, &dev_attr_config_imod); if (ret) dev_dbg(&pdev->dev, "%s: unable to create imod sysfs entry\n", __func__); /* Enable HSIC PHY */ mxhci_hsic_ulpi_write(mxhci, 0x01, MSM_HSIC_CFG_SET); device_init_wakeup(&pdev->dev, 1); wakeup_source_init(&mxhci->ws, dev_name(&pdev->dev)); pm_stay_awake(mxhci->dev); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); return 0; delete_wq: destroy_workqueue(mxhci->wq); remove_usb3_hcd: usb_remove_hcd(xhci->shared_hcd); put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); remove_usb2_hcd: usb_remove_hcd(hcd); deinit_vddcx: mxhci_hsic_init_vddcx(mxhci, 0); deinit_clocks: mxhci_hsic_init_clocks(mxhci, 0); put_hcd: usb_put_hcd(hcd); return ret; }
static int whc_probe(struct umc_dev *umc) { int ret = -ENOMEM; struct usb_hcd *usb_hcd; struct wusbhc *wusbhc = NULL; struct whc *whc = NULL; struct device *dev = &umc->dev; usb_hcd = usb_create_hcd(&whc_hc_driver, dev, "whci"); if (usb_hcd == NULL) { dev_err(dev, "unable to create hcd\n"); goto error; } usb_hcd->wireless = 1; usb_hcd->self.sg_tablesize = 2048; /* somewhat arbitrary */ wusbhc = usb_hcd_to_wusbhc(usb_hcd); whc = wusbhc_to_whc(wusbhc); whc->umc = umc; ret = whc_init(whc); if (ret) goto error; wusbhc->dev = dev; wusbhc->uwb_rc = uwb_rc_get_by_grandpa(umc->dev.parent); if (!wusbhc->uwb_rc) { ret = -ENODEV; dev_err(dev, "cannot get radio controller\n"); goto error; } if (whc->n_devices > USB_MAXCHILDREN) { dev_warn(dev, "USB_MAXCHILDREN too low for WUSB adapter (%u ports)\n", whc->n_devices); wusbhc->ports_max = USB_MAXCHILDREN; } else wusbhc->ports_max = whc->n_devices; wusbhc->mmcies_max = whc->n_mmc_ies; wusbhc->start = whc_wusbhc_start; wusbhc->stop = whc_wusbhc_stop; wusbhc->mmcie_add = whc_mmcie_add; wusbhc->mmcie_rm = whc_mmcie_rm; wusbhc->dev_info_set = whc_dev_info_set; wusbhc->bwa_set = whc_bwa_set; wusbhc->set_num_dnts = whc_set_num_dnts; wusbhc->set_ptk = whc_set_ptk; wusbhc->set_gtk = whc_set_gtk; ret = wusbhc_create(wusbhc); if (ret) goto error_wusbhc_create; ret = usb_add_hcd(usb_hcd, whc->umc->irq, IRQF_SHARED); if (ret) { dev_err(dev, "cannot add HCD: %d\n", ret); goto error_usb_add_hcd; } ret = wusbhc_b_create(wusbhc); if (ret) { dev_err(dev, "WUSBHC phase B setup failed: %d\n", ret); goto error_wusbhc_b_create; } whc_dbg_init(whc); return 0; error_wusbhc_b_create: usb_remove_hcd(usb_hcd); error_usb_add_hcd: wusbhc_destroy(wusbhc); error_wusbhc_create: uwb_rc_put(wusbhc->uwb_rc); error: whc_clean_up(whc); if (usb_hcd) usb_put_hcd(usb_hcd); return ret; }
static int xhci_plat_probe(struct platform_device *pdev) { const struct of_device_id *match; const struct hc_driver *driver; struct xhci_hcd *xhci; struct resource *res; struct usb_hcd *hcd; struct clk *clk; int ret; int irq; if (usb_disabled()) return -ENODEV; driver = &xhci_plat_hc_driver; irq = platform_get_irq(pdev, 0); if (irq < 0) return -ENODEV; /* Try to set 64-bit DMA first */ if (WARN_ON(!pdev->dev.dma_mask)) /* Platform did not initialize dma_mask */ ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); else ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); /* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */ if (ret) { ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); if (ret) return ret; } hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); hcd->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(hcd->regs)) { ret = PTR_ERR(hcd->regs); goto put_hcd; } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); /* * Not all platforms have a clk so it is not an error if the * clock does not exists. */ clk = devm_clk_get(&pdev->dev, NULL); if (!IS_ERR(clk)) { ret = clk_prepare_enable(clk); if (ret) goto put_hcd; } else if (PTR_ERR(clk) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; goto put_hcd; } xhci = hcd_to_xhci(hcd); match = of_match_node(usb_xhci_of_match, pdev->dev.of_node); if (match) { const struct xhci_plat_priv *priv_match = match->data; struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); /* Just copy data for now */ if (priv_match) *priv = *priv_match; } device_wakeup_enable(hcd->self.controller); xhci->clk = clk; xhci->main_hcd = hcd; xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev, dev_name(&pdev->dev), hcd); if (!xhci->shared_hcd) { ret = -ENOMEM; goto disable_clk; } if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable")) xhci->quirks |= XHCI_LPM_SUPPORT; if (HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; hcd->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0); if (IS_ERR(hcd->usb_phy)) { ret = PTR_ERR(hcd->usb_phy); if (ret == -EPROBE_DEFER) goto put_usb3_hcd; hcd->usb_phy = NULL; } else { ret = usb_phy_init(hcd->usb_phy); if (ret) goto put_usb3_hcd; } ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto disable_usb_phy; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto dealloc_usb2_hcd; return 0; dealloc_usb2_hcd: usb_remove_hcd(hcd); disable_usb_phy: usb_phy_shutdown(hcd->usb_phy); put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); disable_clk: if (!IS_ERR(clk)) clk_disable_unprepare(clk); put_hcd: usb_put_hcd(hcd); return ret; }
static int tegra_ehci_probe(struct platform_device *pdev) { struct resource *res; struct tegra_hcd_platform_data *pdata = pdev->dev.platform_data; struct usb_hcd *hcd; int e = 0; int irq; unsigned int temp; struct ehci_hcd *ehci; if (!pdata) { dev_err(&pdev->dev, "platform data must be specified\n"); return -EINVAL; } WARN_ON(!pdev->dev.coherent_dma_mask || !pdev->dev.dma_mask); hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev, dev_name(&pdev->dev)); if (IS_ERR_OR_NULL(hcd)) { dev_err(&pdev->dev, "Unable to create HCD\n"); return -ENOMEM; } if (pdata->id_detect == ID_PIN_GPIO) { e = gpio_request(pdata->gpio_nr, dev_name(&pdev->dev)); if (e < 0) { dev_err(&pdev->dev, "request ID pin GPIO failed\n"); goto fail_hcd; } e = gpio_direction_input(pdata->gpio_nr); if (e < 0) { dev_err(&pdev->dev, "failed to set ID pin as input\n"); goto fail_gpio; } } INIT_WORK(&pdata->work, tegra_ehci_busy_hint_work); if (pdata->regulator_str != NULL) { struct regulator *vbus_reg = regulator_get(NULL, pdata->regulator_str); if (IS_ERR(vbus_reg)) { pr_err("%s: Unable to acquire %s regulator %ld\n", __func__, pdata->regulator_str, PTR_ERR(vbus_reg)); } else { if (regulator_enable(vbus_reg)) pr_err("%s regulator was not enabled\n", __func__); } } /* Init the tegra USB phy */ if (NvDdkUsbPhyOpen(s_hRmGlobal, pdata->instance, &pdata->hUsbPhy) != NvSuccess) { dev_err(&pdev->dev, "failed to open USB phy DDK\n"); e = -ENODEV; goto fail_gpio; } tegra_ehci_power_up(hcd); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "failed to get I/O memory\n"); e = -ENXIO; goto fail_phy; } if (!pdata->otg_mode) { res = request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev)); if (!res) { dev_err(&pdev->dev, "resource in use\n"); e = -EBUSY; goto fail_phy; } } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); hcd->regs = ioremap(res->start, resource_size(res)); if (!hcd->regs) { e = -ENOMEM; goto fail_mem; } /* Set to Host mode by setting bit 0-1 of USB device mode register */ temp = readl(hcd->regs + TEGRA_USB_USBMODE_REG_OFFSET); writel((temp | TEGRA_USB_USBMODE_HOST), (hcd->regs + TEGRA_USB_USBMODE_REG_OFFSET)); irq = platform_get_irq(pdev, 0); if (!irq) { e = -ENODEV; goto fail_iomap; } set_irq_flags(irq, IRQF_VALID); ehci = hcd_to_ehci(hcd); INIT_WORK(&ehci->irq_work, tegra_ehci_irq_work); e = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (e != 0) { dev_err(&pdev->dev, "failed to add HCD\n"); goto fail_iomap; } platform_set_drvdata(pdev, hcd); #ifdef CONFIG_DMABOUNCE e = dmabounce_register_dev(&pdev->dev, 1024, 32768); if (e != 0) { dev_err(&pdev->dev, "failed to register DMA bounce\n"); goto fail_add; } #endif #ifdef CONFIG_USB_OTG_UTILS if (pdata->otg_mode) { ehci->transceiver = otg_get_transceiver(); if (!ehci->transceiver) { dev_err(&pdev->dev, "Failed to get OTG transceiver\n"); e = -ENODEV; goto fail_dmabounce; } otg_set_host(ehci->transceiver, (struct usb_bus *)hcd); /* Stop the controller and power down the phy, OTG will * start the host driver based on the ID pin * detection */ ehci_halt(ehci); /* reset the host and put the controller in idle mode */ temp = ehci_readl(ehci, &ehci->regs->command); temp |= CMD_RESET; ehci_writel(ehci, temp, &ehci->regs->command); temp = readl(hcd->regs + TEGRA_USB_USBMODE_REG_OFFSET); writel((temp & ~TEGRA_USB_USBMODE_HOST), (hcd->regs + TEGRA_USB_USBMODE_REG_OFFSET)); /* indicate hcd flags, that hardware is not accessable now * in host mode*/ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); tegra_ehci_power_down(hcd); ehci->host_reinited = 0; } else #endif { if (pdata->id_detect == ID_PIN_CABLE_ID) { /* enable the cable ID interrupt */ temp = readl(hcd->regs + TEGRA_USB_PHY_WAKEUP_REG_OFFSET); temp |= TEGRA_USB_ID_INT_ENABLE; temp |= TEGRA_USB_ID_PIN_WAKEUP_ENABLE; writel(temp, (hcd->regs + TEGRA_USB_PHY_WAKEUP_REG_OFFSET)); /* Check if we detect any device connected */ if (temp & TEGRA_USB_ID_PIN_STATUS) { tegra_ehci_power_down(hcd); } else { tegra_ehci_power_up(hcd); } } } return 0; fail_dmabounce: #ifdef CONFIG_DMABOUNCE dmabounce_unregister_dev(&pdev->dev); #endif fail_add: usb_remove_hcd(hcd); fail_iomap: iounmap(hcd->regs); fail_mem: res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, resource_size(res)); fail_phy: NvDdkUsbPhyClose(pdata->hUsbPhy); fail_gpio: if (pdata->gpio_nr) gpio_free(pdata->gpio_nr); fail_hcd: usb_put_hcd(hcd); return e; }
int usb_hcd_msp_probe(const struct hc_driver *driver, struct platform_device *dev) { int retval; struct usb_hcd *hcd; struct resource *res; struct ehci_hcd *ehci ; hcd = usb_create_hcd(driver, &dev->dev, "pmcmsp"); if (!hcd) return -ENOMEM; res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (res == NULL) { pr_debug("No IOMEM resource info for %s.\n", dev->name); retval = -ENOMEM; goto err1; } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, dev->name)) { retval = -EBUSY; goto err1; } hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { pr_debug("ioremap failed"); retval = -ENOMEM; goto err2; } res = platform_get_resource(dev, IORESOURCE_IRQ, 0); if (res == NULL) { dev_err(&dev->dev, "No IRQ resource info for %s.\n", dev->name); retval = -ENOMEM; goto err3; } /* */ retval = usb_hcd_msp_map_regs(to_mspusb_device(dev)); if (retval != 0) goto err3; ehci = hcd_to_ehci(hcd); ehci->big_endian_mmio = 1; ehci->big_endian_desc = 1; retval = usb_add_hcd(hcd, res->start, IRQF_SHARED); if (retval == 0) return 0; usb_remove_hcd(hcd); err3: iounmap(hcd->regs); err2: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err1: usb_put_hcd(hcd); return retval; }
static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev) { const struct mfd_cell *cell = mfd_get_cell(dev); struct resource *regs = platform_get_resource(dev, IORESOURCE_MEM, 0); struct resource *config = platform_get_resource(dev, IORESOURCE_MEM, 1); struct resource *sram = platform_get_resource(dev, IORESOURCE_MEM, 2); int irq = platform_get_irq(dev, 0); struct tmio_hcd *tmio; struct ohci_hcd *ohci; struct usb_hcd *hcd; int ret; if (usb_disabled()) return -ENODEV; if (!cell) return -EINVAL; hcd = usb_create_hcd(&ohci_tmio_hc_driver, &dev->dev, dev_name(&dev->dev)); if (!hcd) { ret = -ENOMEM; goto err_usb_create_hcd; } hcd->rsrc_start = regs->start; hcd->rsrc_len = regs->end - regs->start + 1; tmio = hcd_to_tmio(hcd); spin_lock_init(&tmio->lock); tmio->ccr = ioremap(config->start, config->end - config->start + 1); if (!tmio->ccr) { ret = -ENOMEM; goto err_ioremap_ccr; } hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { ret = -ENOMEM; goto err_ioremap_regs; } if (!dma_declare_coherent_memory(&dev->dev, sram->start, sram->start, sram->end - sram->start + 1, DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE)) { ret = -EBUSY; goto err_dma_declare; } if (cell->enable) { ret = cell->enable(dev); if (ret) goto err_enable; } tmio_start_hc(dev); ohci = hcd_to_ohci(hcd); ohci_hcd_init(ohci); ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); if (ret) goto err_add_hcd; if (ret == 0) return ret; usb_remove_hcd(hcd); err_add_hcd: tmio_stop_hc(dev); if (cell->disable) cell->disable(dev); err_enable: dma_release_declared_memory(&dev->dev); err_dma_declare: iounmap(hcd->regs); err_ioremap_regs: iounmap(tmio->ccr); err_ioremap_ccr: usb_put_hcd(hcd); err_usb_create_hcd: return ret; }
/** * usb_hcd_da8xx_probe - initialize DA8xx-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. */ static int usb_hcd_da8xx_probe(const struct hc_driver *driver, struct platform_device *pdev) { struct da8xx_ohci_root_hub *hub = pdev->dev.platform_data; struct usb_hcd *hcd; struct resource *mem; int error, irq; if (hub == NULL) return -ENODEV; usb11_clk = clk_get(&pdev->dev, "usb11"); if (IS_ERR(usb11_clk)) return PTR_ERR(usb11_clk); usb20_clk = clk_get(&pdev->dev, "usb20"); if (IS_ERR(usb20_clk)) { error = PTR_ERR(usb20_clk); goto err0; } hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { error = -ENOMEM; goto err1; } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { error = -ENODEV; goto err2; } hcd->rsrc_start = mem->start; hcd->rsrc_len = resource_size(mem); if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { dev_dbg(&pdev->dev, "request_mem_region failed\n"); error = -EBUSY; goto err2; } hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_err(&pdev->dev, "ioremap failed\n"); error = -ENOMEM; goto err3; } ohci_hcd_init(hcd_to_ohci(hcd)); irq = platform_get_irq(pdev, 0); if (irq < 0) { error = -ENODEV; goto err4; } error = usb_add_hcd(hcd, irq, 0); if (error) goto err4; if (hub->ocic_notify) { error = hub->ocic_notify(ohci_da8xx_ocic_handler); if (!error) return 0; } usb_remove_hcd(hcd); err4: iounmap(hcd->regs); err3: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err2: usb_put_hcd(hcd); err1: clk_put(usb20_clk); err0: clk_put(usb11_clk); return error; }
static ssize_t store_ehci_power(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct platform_device *pdev = to_platform_device(dev); struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev); struct usb_hcd *hcd = s5p_ehci->hcd; int power_on; int irq; int retval; if (sscanf(buf, "%d", &power_on) != 1) return -EINVAL; device_lock(dev); if (!power_on && s5p_ehci->power_on) { printk(KERN_DEBUG "%s: EHCI turns off\n", __func__); pm_runtime_forbid(dev); s5p_ehci->power_on = 0; usb_remove_hcd(hcd); if (pdata && pdata->phy_exit) pdata->phy_exit(pdev, S5P_USB_PHY_HOST); #if defined(CONFIG_LINK_DEVICE_HSIC) || defined(CONFIG_LINK_DEVICE_USB) /*HSIC IPC control the ACTIVE_STATE*/ if (pdata && pdata->noti_host_states) pdata->noti_host_states(pdev, S5P_HOST_OFF); #endif } else if (power_on) { printk(KERN_DEBUG "%s: EHCI turns on\n", __func__); if (s5p_ehci->power_on) { pm_runtime_forbid(dev); usb_remove_hcd(hcd); #if defined(CONFIG_LINK_DEVICE_HSIC) || defined(CONFIG_LINK_DEVICE_USB) /*HSIC IPC control the ACTIVE_STATE*/ if (pdata && pdata->noti_host_states) pdata->noti_host_states(pdev, S5P_HOST_OFF); #endif } else s5p_ehci_phy_init(pdev); irq = platform_get_irq(pdev, 0); retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (retval < 0) { dev_err(dev, "Power On Fail\n"); goto exit; } s5p_ehci->power_on = 1; #if defined(CONFIG_LINK_DEVICE_HSIC) || defined(CONFIG_LINK_DEVICE_USB) /* Sometimes XMM6262 send remote wakeup when hub enter suspend * So, set the hub waiting 500ms autosuspend delay*/ if (hcd->self.root_hub) pm_runtime_set_autosuspend_delay( &hcd->self.root_hub->dev, msecs_to_jiffies(500)); /*HSIC IPC control the ACTIVE_STATE*/ if (pdata && pdata->noti_host_states) pdata->noti_host_states(pdev, S5P_HOST_ON); #endif pm_runtime_allow(dev); } exit: device_unlock(dev); return count; }
static int xhci_plat_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct usb_xhci_pdata *pdata = dev_get_platdata(&pdev->dev); const struct hc_driver *driver; struct xhci_hcd *xhci; struct resource *res; struct usb_hcd *hcd; struct clk *clk; int ret; int irq; if (usb_disabled()) return -ENODEV; driver = &xhci_plat_xhci_driver; irq = platform_get_irq(pdev, 0); if (irq < 0) return -ENODEV; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; if (of_device_is_compatible(pdev->dev.of_node, "marvell,armada-375-xhci") || of_device_is_compatible(pdev->dev.of_node, "marvell,armada-380-xhci")) { ret = xhci_mvebu_mbus_init_quirk(pdev); if (ret) return ret; } /* Initialize dma_mask and coherent_dma_mask to 32-bits */ ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (ret) return ret; if (!pdev->dev.dma_mask) pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; else dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) return -ENOMEM; hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); hcd->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(hcd->regs)) { ret = PTR_ERR(hcd->regs); goto put_hcd; } /* * Not all platforms have a clk so it is not an error if the * clock does not exists. */ clk = devm_clk_get(&pdev->dev, NULL); if (!IS_ERR(clk)) { ret = clk_prepare_enable(clk); if (ret) goto put_hcd; } ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto disable_clk; device_wakeup_enable(hcd->self.controller); /* USB 2.0 roothub is stored in the platform_device now. */ hcd = platform_get_drvdata(pdev); xhci = hcd_to_xhci(hcd); xhci->clk = clk; xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev, dev_name(&pdev->dev), hcd); if (!xhci->shared_hcd) { ret = -ENOMEM; goto dealloc_usb2_hcd; } if ((node && of_property_read_bool(node, "usb3-lpm-capable")) || (pdata && pdata->usb3_lpm_capable)) xhci->quirks |= XHCI_LPM_SUPPORT; /* * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset) * is called by usb_add_hcd(). */ *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; if (HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto put_usb3_hcd; return 0; put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); dealloc_usb2_hcd: usb_remove_hcd(hcd); disable_clk: if (!IS_ERR(clk)) clk_disable_unprepare(clk); put_hcd: usb_put_hcd(hcd); return ret; }
static int __devinit exynos_xhci_probe(struct platform_device *pdev) { struct dwc3_exynos_data *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; const struct hc_driver *driver = &exynos_xhci_hc_driver; struct exynos_xhci_hcd *exynos_xhci; struct usb_hcd *hcd; struct xhci_hcd *xhci; struct resource *res; int irq; int err; if (usb_disabled()) return -ENODEV; if (!pdata) { dev_err(dev, "No platform data defined\n"); return -ENODEV; } exynos_xhci = devm_kzalloc(dev, sizeof(struct exynos_xhci_hcd), GFP_KERNEL); if (!exynos_xhci) { dev_err(dev, "Not enough memory\n"); return -ENOMEM; } exynos_xhci->dev = dev; exynos_xhci->pdata = pdata; exynos_xhci->core = exynos_drd_bind(pdev); irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "Failed to get IRQ\n"); return -ENXIO; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "Failed to get I/O memory\n"); return -ENXIO; } /* Create and add primary HCD */ hcd = usb_create_hcd(driver, dev, dev_name(dev)); if (!hcd) { dev_err(dev, "Failed to create primary HCD\n"); return -ENOMEM; } exynos_xhci->hcd = hcd; /* Rewrite driver data with our structure */ platform_set_drvdata(pdev, exynos_xhci); hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); if (!devm_request_mem_region(dev, res->start, resource_size(res), dev_name(dev))) { dev_err(dev, "Failed to reserve registers\n"); err = -ENOENT; goto put_hcd; } hcd->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); if (!hcd->regs) { dev_err(dev, "Failed to remap I/O memory\n"); err = -ENOMEM; goto put_hcd; } hcd->regs -= EXYNOS_USB3_XHCI_REG_START; err = exynos_drd_try_get(pdev); if (err) { /* REVISIT: what shall we do if UDC is already running */ dev_err(dev, "Failed to access DRD\n"); goto put_hcd; } /* Wake up and initialize DRD core */ pm_runtime_get_sync(dev->parent); if (exynos_xhci->core->ops->change_mode) exynos_xhci->core->ops->change_mode(exynos_xhci->core, true); if (exynos_xhci->core->ops->core_init) exynos_xhci->core->ops->core_init(exynos_xhci->core); err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { dev_err(dev, "Failed to add primary HCD\n"); goto put_hcd; } /* Create and add shared HCD */ xhci = hcd_to_xhci(hcd); exynos_xhci_dbg = xhci; xhci->shared_hcd = usb_create_shared_hcd(driver, dev, dev_name(dev), hcd); if (!xhci->shared_hcd) { dev_err(dev, "Failed to create shared HCD\n"); err = -ENOMEM; goto remove_hcd; } xhci->shared_hcd->regs = hcd->regs; /* * Set the xHCI pointer before exynos_xhci_setup() * (aka hcd_driver.reset) is called by usb_add_hcd(). */ *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; err = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (err) { dev_err(dev, "Failed to add shared HCD\n"); goto put_usb3_hcd; } pm_runtime_set_active(dev); pm_runtime_enable(dev); if (exynos_xhci->core->otg) { err = otg_set_host(exynos_xhci->core->otg, &hcd->self); if (err) { dev_err(dev, "Unable to bind hcd to DRD switch\n"); goto remove_usb3_hcd; } } return 0; remove_usb3_hcd: pm_runtime_disable(dev); usb_remove_hcd(xhci->shared_hcd); put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); remove_hcd: usb_remove_hcd(hcd); put_hcd: usb_put_hcd(hcd); return err; }
void str9100_usb_hcd_remove(struct usb_hcd *hcd, struct platform_device *pdev) { usb_remove_hcd(hcd); usb_put_hcd(hcd); }
static void msm_hsusb_request_host(void *handle, int request) { struct msmusb_hcd *mhcd = handle; struct usb_hcd *hcd = mhcd_to_hcd(mhcd); struct msm_usb_host_platform_data *pdata = mhcd->pdata; struct msm_otg *otg = container_of(mhcd->xceiv, struct msm_otg, otg); #ifdef CONFIG_USB_OTG struct usb_device *udev = hcd->self.root_hub; #endif struct device *dev = hcd->self.controller; switch (request) { #ifdef CONFIG_USB_OTG case REQUEST_HNP_SUSPEND: /* disable Root hub auto suspend. As hardware is configured * for peripheral mode, mark hardware is not available. */ if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED) { pm_runtime_disable(&udev->dev); /* Mark root hub as disconnected. This would * protect suspend/resume via sysfs. */ udev->state = USB_STATE_NOTATTACHED; clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); hcd->state = HC_STATE_HALT; pm_runtime_put_noidle(dev); pm_runtime_suspend(dev); } break; case REQUEST_HNP_RESUME: if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED) { pm_runtime_get_noresume(dev); pm_runtime_resume(dev); disable_irq(hcd->irq); ehci_msm_reset(hcd); ehci_msm_run(hcd); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); pm_runtime_enable(&udev->dev); udev->state = USB_STATE_CONFIGURED; enable_irq(hcd->irq); } break; #endif case REQUEST_RESUME: usb_hcd_resume_root_hub(hcd); break; case REQUEST_START: if (mhcd->running) break; pm_runtime_get_noresume(dev); pm_runtime_resume(dev); wake_lock(&mhcd->wlock); msm_xusb_pm_qos_update(mhcd, 1); msm_xusb_enable_clks(mhcd); if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED) if (otg->set_clk) otg->set_clk(mhcd->xceiv, 1); if (pdata->vbus_power) pdata->vbus_power(pdata->phy_info, 1); if (pdata->config_gpio) pdata->config_gpio(1); usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); mhcd->running = 1; if (PHY_TYPE(pdata->phy_info) == USB_PHY_INTEGRATED) if (otg->set_clk) otg->set_clk(mhcd->xceiv, 0); break; case REQUEST_STOP: if (!mhcd->running) break; mhcd->running = 0; /* come out of lpm before deregistration */ if (PHY_TYPE(pdata->phy_info) == USB_PHY_SERIAL_PMIC) { usb_lpm_exit(hcd); if (cancel_work_sync(&(mhcd->lpm_exit_work))) usb_lpm_exit_w(&mhcd->lpm_exit_work); } usb_remove_hcd(hcd); if (pdata->config_gpio) pdata->config_gpio(0); if (pdata->vbus_power) pdata->vbus_power(pdata->phy_info, 0); msm_xusb_disable_clks(mhcd); wake_lock_timeout(&mhcd->wlock, HZ/2); msm_xusb_pm_qos_update(mhcd, 0); pm_runtime_put_noidle(dev); pm_runtime_suspend(dev); break; } }
static ssize_t store_ehci_power(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct platform_device *pdev = to_platform_device(dev); struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev); struct usb_hcd *hcd = s5p_ehci->hcd; int power_on; int irq; int retval; if (sscanf(buf, "%d", &power_on) != 1) return -EINVAL; device_lock(dev); if (!power_on && s5p_ehci->power_on) { printk(KERN_DEBUG "%s: EHCI turns off\n", __func__); #if defined(CONFIG_LINK_DEVICE_HSIC) || defined(CONFIG_LINK_DEVICE_USB) if (hcd->self.root_hub) pm_runtime_forbid(&hcd->self.root_hub->dev); #endif pm_runtime_forbid(dev); s5p_ehci->power_on = 0; usb_remove_hcd(hcd); if (pdata && pdata->phy_exit) pdata->phy_exit(pdev, S5P_USB_PHY_HOST); } else if (power_on) { printk(KERN_DEBUG "%s: EHCI turns on\n", __func__); if (s5p_ehci->power_on) { pm_runtime_forbid(dev); usb_remove_hcd(hcd); } else s5p_ehci_phy_init(pdev); irq = platform_get_irq(pdev, 0); retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (retval < 0) { dev_err(dev, "Power On Fail\n"); goto exit; } /* * EHCI root hubs are expected to handle remote wakeup. * So, wakeup flag init defaults for root hubs. */ device_wakeup_enable(&hcd->self.root_hub->dev); s5p_ehci->power_on = 1; #if defined(CONFIG_LINK_DEVICE_HSIC) || defined(CONFIG_LINK_DEVICE_USB) /* Sometimes XMM6262 send remote wakeup when hub enter suspend * So, set the hub waiting 500ms autosuspend delay*/ if (hcd->self.root_hub) pm_runtime_set_autosuspend_delay( &hcd->self.root_hub->dev, 500); /* mif allow the ehci runtime after enumeration */ pm_runtime_forbid(dev); #else pm_runtime_allow(dev); #endif } exit: device_unlock(dev); return count; }
static int xhci_plat_probe(struct platform_device *pdev) { const struct hc_driver *driver; struct xhci_hcd *xhci; struct resource *res; struct usb_hcd *hcd; int ret; int irq; if (usb_disabled()) return -ENODEV; driver = &xhci_plat_xhci_driver; irq = platform_get_irq(pdev, 0); if (irq < 0) return -ENODEV; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; /* Initialize dma_mask and coherent_dma_mask to 32-bits */ ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (ret) return ret; if (!pdev->dev.dma_mask) pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; else dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) return -ENOMEM; hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, driver->description)) { dev_dbg(&pdev->dev, "controller already in use\n"); ret = -EBUSY; goto put_hcd; } hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_dbg(&pdev->dev, "error mapping memory\n"); ret = -EFAULT; goto release_mem_region; } ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto unmap_registers; /* USB 2.0 roothub is stored in the platform_device now. */ hcd = platform_get_drvdata(pdev); xhci = hcd_to_xhci(hcd); xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev, dev_name(&pdev->dev), hcd); if (!xhci->shared_hcd) { ret = -ENOMEM; goto dealloc_usb2_hcd; } /* * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset) * is called by usb_add_hcd(). */ *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto put_usb3_hcd; return 0; put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); dealloc_usb2_hcd: usb_remove_hcd(hcd); unmap_registers: iounmap(hcd->regs); release_mem_region: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); put_hcd: usb_put_hcd(hcd); return ret; }
static int xhci_histb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct xhci_hcd_histb *histb; const struct hc_driver *driver; struct usb_hcd *hcd; struct xhci_hcd *xhci; struct resource *res; int irq; int ret = -ENODEV; if (usb_disabled()) return -ENODEV; driver = &xhci_histb_hc_driver; histb = devm_kzalloc(dev, sizeof(*histb), GFP_KERNEL); if (!histb) return -ENOMEM; histb->dev = dev; irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); histb->ctrl = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(histb->ctrl)) return PTR_ERR(histb->ctrl); ret = xhci_histb_clks_get(histb); if (ret) return ret; histb->soft_reset = devm_reset_control_get(dev, "soft"); if (IS_ERR(histb->soft_reset)) { dev_err(dev, "failed to get soft reset\n"); return PTR_ERR(histb->soft_reset); } pm_runtime_enable(dev); pm_runtime_get_sync(dev); device_enable_async_suspend(dev); /* Initialize dma_mask and coherent_dma_mask to 32-bits */ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); if (ret) return ret; hcd = usb_create_hcd(driver, dev, dev_name(dev)); if (!hcd) { ret = -ENOMEM; goto disable_pm; } hcd->regs = histb->ctrl; hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); histb->hcd = hcd; dev_set_drvdata(hcd->self.controller, histb); ret = xhci_histb_host_enable(histb); if (ret) goto put_hcd; xhci = hcd_to_xhci(hcd); device_wakeup_enable(hcd->self.controller); xhci->main_hcd = hcd; xhci->shared_hcd = usb_create_shared_hcd(driver, dev, dev_name(dev), hcd); if (!xhci->shared_hcd) { ret = -ENOMEM; goto disable_host; } if (device_property_read_bool(dev, "usb2-lpm-disable")) xhci->quirks |= XHCI_HW_LPM_DISABLE; if (device_property_read_bool(dev, "usb3-lpm-capable")) xhci->quirks |= XHCI_LPM_SUPPORT; /* imod_interval is the interrupt moderation value in nanoseconds. */ xhci->imod_interval = 40000; device_property_read_u32(dev, "imod-interval-ns", &xhci->imod_interval); ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto put_usb3_hcd; if (HCC_MAX_PSA(xhci->hcc_params) >= 4) xhci->shared_hcd->can_do_streams = 1; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); if (ret) goto dealloc_usb2_hcd; device_enable_async_suspend(dev); pm_runtime_put_noidle(dev); /* * Prevent runtime pm from being on as default, users should enable * runtime pm using power/control in sysfs. */ pm_runtime_forbid(dev); return 0; dealloc_usb2_hcd: usb_remove_hcd(hcd); put_usb3_hcd: usb_put_hcd(xhci->shared_hcd); disable_host: xhci_histb_host_disable(histb); put_hcd: usb_put_hcd(hcd); disable_pm: pm_runtime_put_sync(dev); pm_runtime_disable(dev); return ret; }