static int __init msm_otg_probe(struct platform_device *pdev) { int ret = 0; struct resource *res; struct msm_otg *motg; struct otg_transceiver *otg; dev_info(&pdev->dev, "msm_otg probe\n"); if (!pdev->dev.platform_data) { dev_err(&pdev->dev, "No platform data given. Bailing out\n"); return -ENODEV; } motg = kzalloc(sizeof(struct msm_otg), GFP_KERNEL); if (!motg) { dev_err(&pdev->dev, "unable to allocate msm_otg\n"); return -ENOMEM; } motg->pdata = pdev->dev.platform_data; otg = &motg->otg; otg->dev = &pdev->dev; motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk"); if (IS_ERR(motg->phy_reset_clk)) { dev_err(&pdev->dev, "failed to get usb_phy_clk\n"); ret = PTR_ERR(motg->phy_reset_clk); goto free_motg; } motg->clk = clk_get(&pdev->dev, "usb_hs_clk"); if (IS_ERR(motg->clk)) { dev_err(&pdev->dev, "failed to get usb_hs_clk\n"); ret = PTR_ERR(motg->clk); goto put_phy_reset_clk; } motg->pclk = clk_get(&pdev->dev, "usb_hs_pclk"); if (IS_ERR(motg->pclk)) { dev_err(&pdev->dev, "failed to get usb_hs_pclk\n"); ret = PTR_ERR(motg->pclk); goto put_clk; } /* * USB core clock is not present on all MSM chips. This * clock is introduced to remove the dependency on AXI * bus frequency. */ motg->core_clk = clk_get(&pdev->dev, "usb_hs_core_clk"); if (IS_ERR(motg->core_clk)) motg->core_clk = NULL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "failed to get platform resource mem\n"); ret = -ENODEV; goto put_core_clk; } motg->regs = ioremap(res->start, resource_size(res)); if (!motg->regs) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENOMEM; goto put_core_clk; } dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs); motg->irq = platform_get_irq(pdev, 0); if (!motg->irq) { dev_err(&pdev->dev, "platform_get_irq failed\n"); ret = -ENODEV; goto free_regs; } clk_enable(motg->clk); clk_enable(motg->pclk); if (motg->core_clk) clk_enable(motg->core_clk); writel(0, USB_USBINTR); writel(0, USB_OTGSC); INIT_WORK(&motg->sm_work, msm_otg_sm_work); ret = request_irq(motg->irq, msm_otg_irq, IRQF_SHARED, "msm_otg", motg); if (ret) { dev_err(&pdev->dev, "request irq failed\n"); goto disable_clks; } otg->init = msm_otg_reset; otg->set_host = msm_otg_set_host; otg->set_peripheral = msm_otg_set_peripheral; otg->io_ops = &msm_otg_io_ops; ret = otg_set_transceiver(&motg->otg); if (ret) { dev_err(&pdev->dev, "otg_set_transceiver failed\n"); goto free_irq; } platform_set_drvdata(pdev, motg); device_init_wakeup(&pdev->dev, 1); if (motg->pdata->mode == USB_OTG && motg->pdata->otg_control == OTG_USER_CONTROL) { ret = msm_otg_debugfs_init(motg); if (ret) dev_dbg(&pdev->dev, "mode debugfs file is" "not available\n"); } pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); return 0; free_irq: free_irq(motg->irq, motg); disable_clks: clk_disable(motg->pclk); clk_disable(motg->clk); free_regs: iounmap(motg->regs); put_core_clk: if (motg->core_clk) clk_put(motg->core_clk); clk_put(motg->pclk); put_clk: clk_put(motg->clk); put_phy_reset_clk: clk_put(motg->phy_reset_clk); free_motg: kfree(motg); return ret; }
static int msm_otg_probe(struct platform_device *pdev) { struct regulator_bulk_data regs[3]; int ret = 0; struct device_node *np = pdev->dev.of_node; struct msm_otg_platform_data *pdata; struct resource *res; struct msm_otg *motg; struct usb_phy *phy; void __iomem *phy_select; motg = devm_kzalloc(&pdev->dev, sizeof(struct msm_otg), GFP_KERNEL); if (!motg) { dev_err(&pdev->dev, "unable to allocate msm_otg\n"); return -ENOMEM; } pdata = dev_get_platdata(&pdev->dev); if (!pdata) { if (!np) return -ENXIO; ret = msm_otg_read_dt(pdev, motg); if (ret) return ret; } motg->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), GFP_KERNEL); if (!motg->phy.otg) { dev_err(&pdev->dev, "unable to allocate msm_otg\n"); return -ENOMEM; } phy = &motg->phy; phy->dev = &pdev->dev; motg->phy_reset_clk = devm_clk_get(&pdev->dev, np ? "phy" : "usb_phy_clk"); if (IS_ERR(motg->phy_reset_clk)) { dev_err(&pdev->dev, "failed to get usb_phy_clk\n"); motg->phy_reset_clk = NULL; } motg->clk = devm_clk_get(&pdev->dev, np ? "core" : "usb_hs_clk"); if (IS_ERR(motg->clk)) { dev_err(&pdev->dev, "failed to get usb_hs_clk\n"); return PTR_ERR(motg->clk); } /* * If USB Core is running its protocol engine based on CORE CLK, * CORE CLK must be running at >55Mhz for correct HSUSB * operation and USB core cannot tolerate frequency changes on * CORE CLK. */ motg->pclk = devm_clk_get(&pdev->dev, np ? "iface" : "usb_hs_pclk"); if (IS_ERR(motg->pclk)) { dev_err(&pdev->dev, "failed to get usb_hs_pclk\n"); return PTR_ERR(motg->pclk); } /* * USB core clock is not present on all MSM chips. This * clock is introduced to remove the dependency on AXI * bus frequency. */ motg->core_clk = devm_clk_get(&pdev->dev, np ? "alt_core" : "usb_hs_core_clk"); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -EINVAL; motg->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!motg->regs) return -ENOMEM; /* * NOTE: The PHYs can be multiplexed between the chipidea controller * and the dwc3 controller, using a single bit. It is important that * the dwc3 driver does not set this bit in an incompatible way. */ if (motg->phy_number) { phy_select = devm_ioremap_nocache(&pdev->dev, USB2_PHY_SEL, 4); if (!phy_select) return -ENOMEM; /* Enable second PHY with the OTG port */ writel(0x1, phy_select); } dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs); motg->irq = platform_get_irq(pdev, 0); if (motg->irq < 0) { dev_err(&pdev->dev, "platform_get_irq failed\n"); return motg->irq; } regs[0].supply = "vddcx"; regs[1].supply = "v3p3"; regs[2].supply = "v1p8"; ret = devm_regulator_bulk_get(motg->phy.dev, ARRAY_SIZE(regs), regs); if (ret) return ret; motg->vddcx = regs[0].consumer; motg->v3p3 = regs[1].consumer; motg->v1p8 = regs[2].consumer; clk_set_rate(motg->clk, 60000000); clk_prepare_enable(motg->clk); clk_prepare_enable(motg->pclk); if (!IS_ERR(motg->core_clk)) clk_prepare_enable(motg->core_clk); ret = msm_hsusb_init_vddcx(motg, 1); if (ret) { dev_err(&pdev->dev, "hsusb vddcx configuration failed\n"); goto disable_clks; } ret = msm_hsusb_ldo_init(motg, 1); if (ret) { dev_err(&pdev->dev, "hsusb vreg configuration failed\n"); goto disable_vddcx; } ret = msm_hsusb_ldo_set_mode(motg, 1); if (ret) { dev_err(&pdev->dev, "hsusb vreg enable failed\n"); goto disable_ldo; } writel(0, USB_USBINTR); writel(0, USB_OTGSC); INIT_WORK(&motg->sm_work, msm_otg_sm_work); INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work); ret = devm_request_irq(&pdev->dev, motg->irq, msm_otg_irq, IRQF_SHARED, "msm_otg", motg); if (ret) { dev_err(&pdev->dev, "request irq failed\n"); goto disable_ldo; } phy->init = msm_phy_init; phy->set_power = msm_otg_set_power; phy->notify_disconnect = msm_phy_notify_disconnect; phy->type = USB_PHY_TYPE_USB2; phy->io_ops = &msm_otg_io_ops; phy->otg->phy = &motg->phy; phy->otg->set_host = msm_otg_set_host; phy->otg->set_peripheral = msm_otg_set_peripheral; msm_usb_reset(phy); ret = usb_add_phy_dev(&motg->phy); if (ret) { dev_err(&pdev->dev, "usb_add_phy failed\n"); goto disable_ldo; } platform_set_drvdata(pdev, motg); device_init_wakeup(&pdev->dev, 1); if (motg->pdata->mode == USB_DR_MODE_OTG && motg->pdata->otg_control == OTG_USER_CONTROL) { ret = msm_otg_debugfs_init(motg); if (ret) dev_dbg(&pdev->dev, "Can not create mode change file\n"); } pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); return 0; disable_ldo: msm_hsusb_ldo_init(motg, 0); disable_vddcx: msm_hsusb_init_vddcx(motg, 0); disable_clks: clk_disable_unprepare(motg->pclk); clk_disable_unprepare(motg->clk); if (!IS_ERR(motg->core_clk)) clk_disable_unprepare(motg->core_clk); return ret; }
static int __init msm_otg_probe(struct platform_device *pdev) { int ret = 0; struct resource *res; struct msm_otg *dev; struct msm_otg_platform_data *pdata; dev = kzalloc(sizeof(struct msm_otg), GFP_KERNEL); if (!dev) return -ENOMEM; dev->otg.dev = &pdev->dev; if (pdev->dev.platform_data) { pdata = pdev->dev.platform_data; dev->rpc_connect = pdata->rpc_connect; dev->phy_reset = pdata->phy_reset; } if (dev->rpc_connect) { ret = dev->rpc_connect(1); pr_info("%s: rpc_connect(%d)\n", __func__, ret); if (ret) { pr_err("%s: rpc connect failed\n", __func__); ret = -ENODEV; goto free_dev; } } dev->clk = clk_get(&pdev->dev, "usb_hs_clk"); if (IS_ERR(dev->clk)) { pr_err("%s: failed to get usb_hs_clk\n", __func__); ret = PTR_ERR(dev->clk); goto rpc_fail; } dev->pclk = clk_get(&pdev->dev, "usb_hs_pclk"); if (IS_ERR(dev->clk)) { pr_err("%s: failed to get usb_hs_pclk\n", __func__); ret = PTR_ERR(dev->pclk); goto put_clk; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { pr_err("%s: failed to get platform resource mem\n", __func__); ret = -ENODEV; goto put_pclk; } dev->regs = ioremap(res->start, resource_size(res)); if (!dev->regs) { pr_err("%s: ioremap failed\n", __func__); ret = -ENOMEM; goto put_pclk; } dev->irq = platform_get_irq(pdev, 0); if (!dev->irq) { pr_err("%s: platform_get_irq failed\n", __func__); ret = -ENODEV; goto free_regs; } /* enable clocks */ clk_enable(dev->clk); clk_enable(dev->pclk); otg_reset(dev); ret = request_irq(dev->irq, msm_otg_irq, IRQF_SHARED, "msm_otg", dev); if (ret) { pr_info("%s: request irq failed\n", __func__); clk_disable(dev->clk); clk_disable(dev->pclk); goto free_regs; } the_msm_otg = dev; dev->otg.set_peripheral = msm_otg_set_peripheral; dev->otg.set_host = msm_otg_set_host; dev->otg.set_suspend = msm_otg_set_suspend; if (otg_set_transceiver(&dev->otg)) { WARN_ON(1); goto free_regs; } wake_lock_init(&dev->wlock, WAKE_LOCK_SUSPEND, "usb_bus_active"); wake_lock(&dev->wlock); msm_otg_debugfs_init(dev); device_init_wakeup(&pdev->dev, 1); return 0; free_regs: iounmap(dev->regs); put_pclk: clk_put(dev->pclk); put_clk: clk_put(dev->clk); rpc_fail: dev->rpc_connect(0); free_dev: kfree(dev); return ret; }