static int imx_chipidea_probe_dt(struct imx_chipidea *ci) { const void *out_args; struct device_node *usbmisc_np; enum usb_dr_mode mode; enum usb_phy_interface phymode; of_parse_phandles_with_args(ci->dev->device_node, "fsl,usbmisc", "#index-cells", 0, &usbmisc_np, &out_args); ci->portno = be32_to_cpup(out_args); ci->flags = MXC_EHCI_MODE_UTMI_8BIT; mode = of_usb_get_dr_mode(ci->dev->device_node, NULL); switch (mode) { case USB_DR_MODE_HOST: default: ci->mode = IMX_USB_MODE_HOST; break; case USB_DR_MODE_PERIPHERAL: ci->mode = IMX_USB_MODE_DEVICE; break; } phymode = of_usb_get_phy_mode(ci->dev->device_node, NULL); switch (phymode) { case USBPHY_INTERFACE_MODE_UTMI: ci->flags = MXC_EHCI_MODE_UTMI_8BIT; break; case USBPHY_INTERFACE_MODE_UTMIW: ci->flags = MXC_EHCI_MODE_UTMI_16_BIT; break; case USBPHY_INTERFACE_MODE_ULPI: ci->flags = MXC_EHCI_MODE_ULPI; break; case USBPHY_INTERFACE_MODE_SERIAL: ci->flags = MXC_EHCI_MODE_SERIAL; break; case USBPHY_INTERFACE_MODE_HSIC: ci->flags = MXC_EHCI_MODE_HSIC; break; default: dev_err(ci->dev, "no or invalid phy mode setting\n"); return -EINVAL; } if (of_find_property(ci->dev->device_node, "disable-over-current")) ci->flags |= MXC_EHCI_DISABLE_OVERCURRENT; return 0; }
static int imx_chipidea_probe_dt(struct imx_chipidea *ci) { struct of_phandle_args out_args; enum usb_dr_mode mode; if (of_parse_phandle_with_args(ci->dev->device_node, "fsl,usbmisc", "#index-cells", 0, &out_args)) return -ENODEV; ci->portno = out_args.args[0]; ci->flags = MXC_EHCI_MODE_UTMI_8BIT; mode = of_usb_get_dr_mode(ci->dev->device_node, NULL); switch (mode) { case USB_DR_MODE_HOST: default: ci->mode = IMX_USB_MODE_HOST; break; case USB_DR_MODE_PERIPHERAL: ci->mode = IMX_USB_MODE_DEVICE; break; } ci->phymode = of_usb_get_phy_mode(ci->dev->device_node, NULL); switch (ci->phymode) { case USBPHY_INTERFACE_MODE_UTMI: ci->flags = MXC_EHCI_MODE_UTMI_8BIT; break; case USBPHY_INTERFACE_MODE_UTMIW: ci->flags = MXC_EHCI_MODE_UTMI_16_BIT; break; case USBPHY_INTERFACE_MODE_ULPI: ci->flags = MXC_EHCI_MODE_ULPI; break; case USBPHY_INTERFACE_MODE_SERIAL: ci->flags = MXC_EHCI_MODE_SERIAL; break; case USBPHY_INTERFACE_MODE_HSIC: ci->flags = MXC_EHCI_MODE_HSIC; break; default: dev_dbg(ci->dev, "no phy_type setting. Relying on reset default\n"); } if (of_find_property(ci->dev->device_node, "disable-over-current", NULL)) ci->flags |= MXC_EHCI_DISABLE_OVERCURRENT; return 0; }
static int get_musb_port_mode(struct device *dev) { enum usb_dr_mode mode; mode = of_usb_get_dr_mode(dev->of_node); switch (mode) { case USB_DR_MODE_HOST: return MUSB_PORT_MODE_HOST; case USB_DR_MODE_PERIPHERAL: return MUSB_PORT_MODE_GADGET; case USB_DR_MODE_UNKNOWN: case USB_DR_MODE_OTG: default: return MUSB_PORT_MODE_DUAL_ROLE; }; }
static int get_musb_port_mode(struct device_d *dev) { enum usb_dr_mode mode; mode = of_usb_get_dr_mode(dev->device_node, NULL); switch (mode) { case USB_DR_MODE_HOST: return MUSB_PORT_MODE_HOST; case USB_DR_MODE_PERIPHERAL: return MUSB_PORT_MODE_GADGET; case USB_DR_MODE_UNKNOWN: case USB_DR_MODE_OTG: default: if (!IS_ENABLED(CONFIG_USB_MUSB_HOST)) return MUSB_PORT_MODE_GADGET; if (!IS_ENABLED(CONFIG_USB_MUSB_GADGET)) return MUSB_PORT_MODE_HOST; return MUSB_PORT_MODE_DUAL_ROLE; } }
static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) { struct msm_otg_platform_data *pdata; const struct of_device_id *id; struct device_node *node = pdev->dev.of_node; struct property *prop; int len, ret, words; u32 val, tmp[3]; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; motg->pdata = pdata; id = of_match_device(msm_otg_dt_match, &pdev->dev); pdata->phy_type = (enum msm_usb_phy_type) id->data; motg->link_rst = devm_reset_control_get(&pdev->dev, "link"); if (IS_ERR(motg->link_rst)) return PTR_ERR(motg->link_rst); motg->phy_rst = devm_reset_control_get(&pdev->dev, "phy"); if (IS_ERR(motg->phy_rst)) motg->phy_rst = NULL; pdata->mode = of_usb_get_dr_mode(node); if (pdata->mode == USB_DR_MODE_UNKNOWN) pdata->mode = USB_DR_MODE_OTG; pdata->otg_control = OTG_PHY_CONTROL; if (!of_property_read_u32(node, "qcom,otg-control", &val)) if (val == OTG_PMIC_CONTROL) pdata->otg_control = val; if (!of_property_read_u32(node, "qcom,phy-num", &val) && val < 2) motg->phy_number = val; motg->vdd_levels[VDD_LEVEL_NONE] = USB_PHY_SUSP_DIG_VOL; motg->vdd_levels[VDD_LEVEL_MIN] = USB_PHY_VDD_DIG_VOL_MIN; motg->vdd_levels[VDD_LEVEL_MAX] = USB_PHY_VDD_DIG_VOL_MAX; if (of_get_property(node, "qcom,vdd-levels", &len) && len == sizeof(tmp)) { of_property_read_u32_array(node, "qcom,vdd-levels", tmp, len / sizeof(*tmp)); motg->vdd_levels[VDD_LEVEL_NONE] = tmp[VDD_LEVEL_NONE]; motg->vdd_levels[VDD_LEVEL_MIN] = tmp[VDD_LEVEL_MIN]; motg->vdd_levels[VDD_LEVEL_MAX] = tmp[VDD_LEVEL_MAX]; } prop = of_find_property(node, "qcom,phy-init-sequence", &len); if (!prop || !len) return 0; words = len / sizeof(u32); if (words >= ULPI_EXT_VENDOR_SPECIFIC) { dev_warn(&pdev->dev, "Too big PHY init sequence %d\n", words); return 0; } pdata->phy_init_seq = devm_kzalloc(&pdev->dev, len, GFP_KERNEL); if (!pdata->phy_init_seq) { dev_warn(&pdev->dev, "No space for PHY init sequence\n"); return 0; } ret = of_property_read_u32_array(node, "qcom,phy-init-sequence", pdata->phy_init_seq, words); if (!ret) pdata->phy_init_sz = words; return 0; }
static int dwc3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct dwc3_platform_data *pdata = dev_get_platdata(dev); struct device_node *node = dev->of_node; struct resource *res; struct dwc3 *dwc; int ret = -ENOMEM; void __iomem *regs; void *mem; mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); if (!mem) { dev_err(dev, "not enough memory\n"); return -ENOMEM; } dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); dwc->mem = mem; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(dev, "missing IRQ\n"); return -ENODEV; } dwc->xhci_resources[1].start = res->start; dwc->xhci_resources[1].end = res->end; dwc->xhci_resources[1].flags = res->flags; dwc->xhci_resources[1].name = res->name; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "missing memory resource\n"); return -ENODEV; } if (node) { dwc->maximum_speed = of_usb_get_maximum_speed(node); dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize"); dwc->dr_mode = of_usb_get_dr_mode(node); } else if (pdata) { dwc->maximum_speed = pdata->maximum_speed; dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); dwc->needs_fifo_resize = pdata->tx_fifo_resize; dwc->dr_mode = pdata->dr_mode; } else { dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); } /* default to superspeed if no maximum_speed passed */ if (dwc->maximum_speed == USB_SPEED_UNKNOWN) dwc->maximum_speed = USB_SPEED_SUPER; if (IS_ERR(dwc->usb2_phy)) { ret = PTR_ERR(dwc->usb2_phy); if (ret == -ENXIO || ret == -ENODEV) { dwc->usb2_phy = NULL; } else if (ret == -EPROBE_DEFER) { return ret; } else { dev_err(dev, "no usb2 phy configured\n"); return ret; } } if (IS_ERR(dwc->usb3_phy)) { ret = PTR_ERR(dwc->usb3_phy); if (ret == -ENXIO || ret == -ENODEV) { dwc->usb3_phy = NULL; } else if (ret == -EPROBE_DEFER) { return ret; } else { dev_err(dev, "no usb3 phy configured\n"); return ret; } } dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); if (IS_ERR(dwc->usb2_generic_phy)) { ret = PTR_ERR(dwc->usb2_generic_phy); if (ret == -ENOSYS || ret == -ENODEV) { dwc->usb2_generic_phy = NULL; } else if (ret == -EPROBE_DEFER) { return ret; } else { dev_err(dev, "no usb2 phy configured\n"); return ret; } } dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); if (IS_ERR(dwc->usb3_generic_phy)) { ret = PTR_ERR(dwc->usb3_generic_phy); if (ret == -ENOSYS || ret == -ENODEV) { dwc->usb3_generic_phy = NULL; } else if (ret == -EPROBE_DEFER) { return ret; } else { dev_err(dev, "no usb3 phy configured\n"); return ret; } } dwc->xhci_resources[0].start = res->start; dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + DWC3_XHCI_REGS_END; dwc->xhci_resources[0].flags = res->flags; dwc->xhci_resources[0].name = res->name; res->start += DWC3_GLOBALS_REGS_START; /* * Request memory region but exclude xHCI regs, * since it will be requested by the xhci-plat driver. */ regs = devm_ioremap_resource(dev, res); if (IS_ERR(regs)) return PTR_ERR(regs); spin_lock_init(&dwc->lock); platform_set_drvdata(pdev, dwc); dwc->regs = regs; dwc->regs_size = resource_size(res); dwc->dev = dev; dev->dma_mask = dev->parent->dma_mask; dev->dma_parms = dev->parent->dma_parms; dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); pm_runtime_enable(dev); pm_runtime_get_sync(dev); pm_runtime_forbid(dev); dwc3_cache_hwparams(dwc); ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); if (ret) { dev_err(dwc->dev, "failed to allocate event buffers\n"); ret = -ENOMEM; goto err0; } if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) dwc->dr_mode = USB_DR_MODE_HOST; else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) dwc->dr_mode = USB_DR_MODE_PERIPHERAL; if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) dwc->dr_mode = USB_DR_MODE_OTG; ret = dwc3_core_init(dwc); if (ret) { dev_err(dev, "failed to initialize core\n"); goto err0; } usb_phy_set_suspend(dwc->usb2_phy, 0); usb_phy_set_suspend(dwc->usb3_phy, 0); ret = phy_power_on(dwc->usb2_generic_phy); if (ret < 0) goto err1; ret = phy_power_on(dwc->usb3_generic_phy); if (ret < 0) goto err_usb2phy_power; ret = dwc3_event_buffers_setup(dwc); if (ret) { dev_err(dwc->dev, "failed to setup event buffers\n"); goto err_usb3phy_power; } switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, "failed to initialize gadget\n"); goto err2; } break; case USB_DR_MODE_HOST: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, "failed to initialize host\n"); goto err2; } break; case USB_DR_MODE_OTG: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, "failed to initialize host\n"); goto err2; } ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, "failed to initialize gadget\n"); goto err2; } break; default: dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); goto err2; } ret = dwc3_debugfs_init(dwc); if (ret) { dev_err(dev, "failed to initialize debugfs\n"); goto err3; } pm_runtime_allow(dev); return 0; err3: switch (dwc->dr_mode) { case USB_DR_MODE_PERIPHERAL: dwc3_gadget_exit(dwc); break; case USB_DR_MODE_HOST: dwc3_host_exit(dwc); break; case USB_DR_MODE_OTG: dwc3_host_exit(dwc); dwc3_gadget_exit(dwc); break; default: /* do nothing */ break; } err2: dwc3_event_buffers_cleanup(dwc); err_usb3phy_power: phy_power_off(dwc->usb3_generic_phy); err_usb2phy_power: phy_power_off(dwc->usb2_generic_phy); err1: usb_phy_set_suspend(dwc->usb2_phy, 1); usb_phy_set_suspend(dwc->usb3_phy, 1); dwc3_core_exit(dwc); err0: dwc3_free_event_buffers(dwc); return ret; }
static int st_dwc3_probe(struct platform_device *pdev) { struct st_dwc3 *dwc3_data; struct resource *res; struct device *dev = &pdev->dev; struct device_node *node = dev->of_node, *child; struct regmap *regmap; int ret; dwc3_data = devm_kzalloc(dev, sizeof(*dwc3_data), GFP_KERNEL); if (!dwc3_data) return -ENOMEM; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "reg-glue"); dwc3_data->glue_base = devm_ioremap_resource(dev, res); if (IS_ERR(dwc3_data->glue_base)) return PTR_ERR(dwc3_data->glue_base); regmap = syscon_regmap_lookup_by_phandle(node, "st,syscfg"); if (IS_ERR(regmap)) return PTR_ERR(regmap); dma_set_coherent_mask(dev, dev->coherent_dma_mask); dwc3_data->dev = dev; dwc3_data->regmap = regmap; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "syscfg-reg"); if (!res) { ret = -ENXIO; goto undo_platform_dev_alloc; } dwc3_data->syscfg_reg_off = res->start; dev_vdbg(&pdev->dev, "glue-logic addr 0x%p, syscfg-reg offset 0x%x\n", dwc3_data->glue_base, dwc3_data->syscfg_reg_off); dwc3_data->rstc_pwrdn = devm_reset_control_get(dev, "powerdown"); if (IS_ERR(dwc3_data->rstc_pwrdn)) { dev_err(&pdev->dev, "could not get power controller\n"); ret = PTR_ERR(dwc3_data->rstc_pwrdn); goto undo_platform_dev_alloc; } /* Manage PowerDown */ reset_control_deassert(dwc3_data->rstc_pwrdn); dwc3_data->rstc_rst = devm_reset_control_get(dev, "softreset"); if (IS_ERR(dwc3_data->rstc_rst)) { dev_err(&pdev->dev, "could not get reset controller\n"); ret = PTR_ERR(dwc3_data->rstc_pwrdn); goto undo_powerdown; } /* Manage SoftReset */ reset_control_deassert(dwc3_data->rstc_rst); child = of_get_child_by_name(node, "dwc3"); if (!child) { dev_err(&pdev->dev, "failed to find dwc3 core node\n"); ret = -ENODEV; goto undo_softreset; } dwc3_data->dr_mode = of_usb_get_dr_mode(child); /* Allocate and initialize the core */ ret = of_platform_populate(node, NULL, NULL, dev); if (ret) { dev_err(dev, "failed to add dwc3 core\n"); goto undo_softreset; } /* * Configure the USB port as device or host according to the static * configuration passed from DT. * DRD is the only mode currently supported so this will be enhanced * as soon as OTG is available. */ ret = st_dwc3_drd_init(dwc3_data); if (ret) { dev_err(dev, "drd initialisation failed\n"); goto undo_softreset; } /* ST glue logic init */ st_dwc3_init(dwc3_data); platform_set_drvdata(pdev, dwc3_data); return 0; undo_softreset: reset_control_assert(dwc3_data->rstc_rst); undo_powerdown: reset_control_assert(dwc3_data->rstc_pwrdn); undo_platform_dev_alloc: platform_device_put(pdev); return ret; }
static int dwc3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct dwc3_platform_data *pdata = dev_get_platdata(dev); struct device_node *node = dev->of_node; struct resource *res; struct dwc3 *dwc; u8 lpm_nyet_threshold; u8 tx_de_emphasis; u8 hird_threshold; int ret; void __iomem *regs; void *mem; mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); if (!mem) return -ENOMEM; dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); dwc->mem = mem; dwc->dev = dev; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(dev, "missing IRQ\n"); return -ENODEV; } dwc->xhci_resources[1].start = res->start; dwc->xhci_resources[1].end = res->end; dwc->xhci_resources[1].flags = res->flags; dwc->xhci_resources[1].name = res->name; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "missing memory resource\n"); return -ENODEV; } dwc->xhci_resources[0].start = res->start; dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + DWC3_XHCI_REGS_END; dwc->xhci_resources[0].flags = res->flags; dwc->xhci_resources[0].name = res->name; res->start += DWC3_GLOBALS_REGS_START; /* * Request memory region but exclude xHCI regs, * since it will be requested by the xhci-plat driver. */ regs = devm_ioremap_resource(dev, res); if (IS_ERR(regs)) { ret = PTR_ERR(regs); goto err0; } dwc->regs = regs; dwc->regs_size = resource_size(res); /* default to highest possible threshold */ lpm_nyet_threshold = 0xff; /* default to -3.5dB de-emphasis */ tx_de_emphasis = 1; /* * default to assert utmi_sleep_n and use maximum allowed HIRD * threshold value of 0b1100 */ hird_threshold = 12; if (node) { dwc->maximum_speed = of_usb_get_maximum_speed(node); dwc->has_lpm_erratum = of_property_read_bool(node, "snps,has-lpm-erratum"); of_property_read_u8(node, "snps,lpm-nyet-threshold", &lpm_nyet_threshold); dwc->is_utmi_l1_suspend = of_property_read_bool(node, "snps,is-utmi-l1-suspend"); of_property_read_u8(node, "snps,hird-threshold", &hird_threshold); dwc->usb3_lpm_capable = of_property_read_bool(node, "snps,usb3_lpm_capable"); dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize"); dwc->dr_mode = of_usb_get_dr_mode(node); dwc->disable_scramble_quirk = of_property_read_bool(node, "snps,disable_scramble_quirk"); dwc->u2exit_lfps_quirk = of_property_read_bool(node, "snps,u2exit_lfps_quirk"); dwc->u2ss_inp3_quirk = of_property_read_bool(node, "snps,u2ss_inp3_quirk"); dwc->req_p1p2p3_quirk = of_property_read_bool(node, "snps,req_p1p2p3_quirk"); dwc->del_p1p2p3_quirk = of_property_read_bool(node, "snps,del_p1p2p3_quirk"); dwc->del_phy_power_chg_quirk = of_property_read_bool(node, "snps,del_phy_power_chg_quirk"); dwc->lfps_filter_quirk = of_property_read_bool(node, "snps,lfps_filter_quirk"); dwc->rx_detect_poll_quirk = of_property_read_bool(node, "snps,rx_detect_poll_quirk"); dwc->dis_u3_susphy_quirk = of_property_read_bool(node, "snps,dis_u3_susphy_quirk"); dwc->dis_u2_susphy_quirk = of_property_read_bool(node, "snps,dis_u2_susphy_quirk"); dwc->dis_enblslpm_quirk = device_property_read_bool(dev, "snps,dis_enblslpm_quirk"); dwc->tx_de_emphasis_quirk = of_property_read_bool(node, "snps,tx_de_emphasis_quirk"); of_property_read_u8(node, "snps,tx_de_emphasis", &tx_de_emphasis); of_property_read_string(node, "snps,hsphy_interface", &dwc->hsphy_interface); } else if (pdata) { dwc->maximum_speed = pdata->maximum_speed; dwc->has_lpm_erratum = pdata->has_lpm_erratum; if (pdata->lpm_nyet_threshold) lpm_nyet_threshold = pdata->lpm_nyet_threshold; dwc->is_utmi_l1_suspend = pdata->is_utmi_l1_suspend; if (pdata->hird_threshold) hird_threshold = pdata->hird_threshold; dwc->needs_fifo_resize = pdata->tx_fifo_resize; dwc->usb3_lpm_capable = pdata->usb3_lpm_capable; dwc->dr_mode = pdata->dr_mode; dwc->disable_scramble_quirk = pdata->disable_scramble_quirk; dwc->u2exit_lfps_quirk = pdata->u2exit_lfps_quirk; dwc->u2ss_inp3_quirk = pdata->u2ss_inp3_quirk; dwc->req_p1p2p3_quirk = pdata->req_p1p2p3_quirk; dwc->del_p1p2p3_quirk = pdata->del_p1p2p3_quirk; dwc->del_phy_power_chg_quirk = pdata->del_phy_power_chg_quirk; dwc->lfps_filter_quirk = pdata->lfps_filter_quirk; dwc->rx_detect_poll_quirk = pdata->rx_detect_poll_quirk; dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk; dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk; dwc->dis_enblslpm_quirk = pdata->dis_enblslpm_quirk; dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk; if (pdata->tx_de_emphasis) tx_de_emphasis = pdata->tx_de_emphasis; dwc->hsphy_interface = pdata->hsphy_interface; } /* default to superspeed if no maximum_speed passed */ if (dwc->maximum_speed == USB_SPEED_UNKNOWN) dwc->maximum_speed = USB_SPEED_SUPER; dwc->lpm_nyet_threshold = lpm_nyet_threshold; dwc->tx_de_emphasis = tx_de_emphasis; dwc->hird_threshold = hird_threshold | (dwc->is_utmi_l1_suspend << 4); platform_set_drvdata(pdev, dwc); dwc3_cache_hwparams(dwc); ret = dwc3_phy_setup(dwc); if (ret) goto err0; ret = dwc3_core_get_phy(dwc); if (ret) goto err0; spin_lock_init(&dwc->lock); if (!dev->dma_mask) { dev->dma_mask = dev->parent->dma_mask; dev->dma_parms = dev->parent->dma_parms; dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); } pm_runtime_enable(dev); pm_runtime_get_sync(dev); pm_runtime_forbid(dev); ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); if (ret) { dev_err(dwc->dev, "failed to allocate event buffers\n"); ret = -ENOMEM; goto err1; } if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) dwc->dr_mode = USB_DR_MODE_HOST; else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) dwc->dr_mode = USB_DR_MODE_PERIPHERAL; if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) dwc->dr_mode = USB_DR_MODE_OTG; ret = dwc3_core_init(dwc); if (ret) { dev_err(dev, "failed to initialize core\n"); goto err1; } usb_phy_set_suspend(dwc->usb2_phy, 0); usb_phy_set_suspend(dwc->usb3_phy, 0); ret = phy_power_on(dwc->usb2_generic_phy); if (ret < 0) goto err2; ret = phy_power_on(dwc->usb3_generic_phy); if (ret < 0) goto err3; ret = dwc3_event_buffers_setup(dwc); if (ret) { dev_err(dwc->dev, "failed to setup event buffers\n"); goto err4; } ret = dwc3_core_init_mode(dwc); if (ret) goto err5; ret = dwc3_debugfs_init(dwc); if (ret) { dev_err(dev, "failed to initialize debugfs\n"); goto err6; } pm_runtime_allow(dev); return 0; err6: dwc3_core_exit_mode(dwc); err5: dwc3_event_buffers_cleanup(dwc); err4: phy_power_off(dwc->usb3_generic_phy); err3: phy_power_off(dwc->usb2_generic_phy); err2: usb_phy_set_suspend(dwc->usb2_phy, 1); usb_phy_set_suspend(dwc->usb3_phy, 1); dwc3_core_exit(dwc); err1: dwc3_free_event_buffers(dwc); dwc3_ulpi_exit(dwc); err0: /* * restore res->start back to its original value so that, in case the * probe is deferred, we don't end up getting error in request the * memory region the next time probe is called. */ res->start -= DWC3_GLOBALS_REGS_START; return ret; }
static int dwc3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct dwc3_platform_data *pdata = dev_get_platdata(dev); struct device_node *node = dev->of_node; struct resource *res; struct dwc3 *dwc; int ret; void __iomem *regs; void *mem; mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); if (!mem) { dev_err(dev, "not enough memory\n"); return -ENOMEM; } dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); dwc->mem = mem; dwc->dev = dev; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(dev, "missing IRQ\n"); return -ENODEV; } dwc->xhci_resources[1].start = res->start; dwc->xhci_resources[1].end = res->end; dwc->xhci_resources[1].flags = res->flags; dwc->xhci_resources[1].name = res->name; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "missing memory resource\n"); return -ENODEV; } dwc->xhci_resources[0].start = res->start; dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + DWC3_XHCI_REGS_END; dwc->xhci_resources[0].flags = res->flags; dwc->xhci_resources[0].name = res->name; res->start += DWC3_GLOBALS_REGS_START; /* * Request memory region but exclude xHCI regs, * since it will be requested by the xhci-plat driver. */ regs = devm_ioremap_resource(dev, res); if (IS_ERR(regs)) return PTR_ERR(regs); dwc->regs = regs; dwc->regs_size = resource_size(res); /* * restore res->start back to its original value so that, * in case the probe is deferred, we don't end up getting error in * request the memory region the next time probe is called. */ res->start -= DWC3_GLOBALS_REGS_START; if (node) { dwc->maximum_speed = of_usb_get_maximum_speed(node); dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize"); dwc->dr_mode = of_usb_get_dr_mode(node); } else if (pdata) { dwc->maximum_speed = pdata->maximum_speed; dwc->needs_fifo_resize = pdata->tx_fifo_resize; dwc->dr_mode = pdata->dr_mode; } /* default to superspeed if no maximum_speed passed */ if (dwc->maximum_speed == USB_SPEED_UNKNOWN) dwc->maximum_speed = USB_SPEED_SUPER; ret = dwc3_core_get_phy(dwc); if (ret) return ret; spin_lock_init(&dwc->lock); platform_set_drvdata(pdev, dwc); dev->dma_mask = dev->parent->dma_mask; dev->dma_parms = dev->parent->dma_parms; dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); pm_runtime_enable(dev); pm_runtime_get_sync(dev); pm_runtime_forbid(dev); dwc3_cache_hwparams(dwc); ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); if (ret) { dev_err(dwc->dev, "failed to allocate event buffers\n"); ret = -ENOMEM; goto err0; } if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) dwc->dr_mode = USB_DR_MODE_HOST; else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) dwc->dr_mode = USB_DR_MODE_PERIPHERAL; if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) dwc->dr_mode = USB_DR_MODE_OTG; ret = dwc3_core_init(dwc); if (ret) { dev_err(dev, "failed to initialize core\n"); goto err0; } usb_phy_set_suspend(dwc->usb2_phy, 0); usb_phy_set_suspend(dwc->usb3_phy, 0); ret = phy_power_on(dwc->usb2_generic_phy); if (ret < 0) goto err1; ret = phy_power_on(dwc->usb3_generic_phy); if (ret < 0) goto err_usb2phy_power; ret = dwc3_event_buffers_setup(dwc); if (ret) { dev_err(dwc->dev, "failed to setup event buffers\n"); goto err_usb3phy_power; } ret = dwc3_core_init_mode(dwc); if (ret) goto err2; ret = dwc3_debugfs_init(dwc); if (ret) { dev_err(dev, "failed to initialize debugfs\n"); goto err3; } pm_runtime_allow(dev); return 0; err3: dwc3_core_exit_mode(dwc); err2: dwc3_event_buffers_cleanup(dwc); err_usb3phy_power: phy_power_off(dwc->usb3_generic_phy); err_usb2phy_power: phy_power_off(dwc->usb2_generic_phy); err1: usb_phy_set_suspend(dwc->usb2_phy, 1); usb_phy_set_suspend(dwc->usb3_phy, 1); dwc3_core_exit(dwc); err0: dwc3_free_event_buffers(dwc); return ret; }