static int msm_ssphy_power_enable(struct msm_ssphy_qmp *phy, bool on) { bool host = phy->phy.flags & PHY_HOST_MODE; int ret = 0; if (!host && !phy->cable_connected) { if (on) { ret = regulator_enable(phy->vdd); if (ret) dev_err(phy->phy.dev, "regulator_enable(phy->vdd) failed, ret=%d", ret); ret = msm_ssusb_qmp_ldo_enable(phy, 1); if (ret) dev_err(phy->phy.dev, "msm_ssusb_qmp_ldo_enable(1) failed, ret=%d\n", ret); } else { ret = msm_ssusb_qmp_ldo_enable(phy, 0); if (ret) dev_err(phy->phy.dev, "msm_ssusb_qmp_ldo_enable(0) failed, ret=%d\n", ret); ret = regulator_disable(phy->vdd); if (ret) dev_err(phy->phy.dev, "regulator_disable(phy->vdd) failed, ret=%d", ret); } } return ret; }
static int msm_ssphy_power_enable(struct msm_ssphy_qmp *phy, bool on) { bool host = phy->phy.flags & PHY_HOST_MODE; bool chg_connected = phy->phy.flags & PHY_CHARGER_CONNECTED; int ret = 0; /* * Turn off the phy's LDOs when cable is disconnected for device mode * with external vbus_id indication. */ if (!host && !chg_connected && !phy->cable_connected) { if (on) { ret = regulator_enable(phy->vdd); if (ret) dev_err(phy->phy.dev, "regulator_enable(phy->vdd) failed, ret=%d", ret); ret = msm_ssusb_qmp_ldo_enable(phy, 1); if (ret) dev_err(phy->phy.dev, "msm_ssusb_qmp_ldo_enable(1) failed, ret=%d\n", ret); } else { ret = msm_ssusb_qmp_ldo_enable(phy, 0); if (ret) dev_err(phy->phy.dev, "msm_ssusb_qmp_ldo_enable(0) failed, ret=%d\n", ret); ret = regulator_disable(phy->vdd); if (ret) dev_err(phy->phy.dev, "regulator_disable(phy->vdd) failed, ret=%d", ret); } } return ret; }
static int msm_ssphy_qmp_remove(struct platform_device *pdev) { struct msm_ssphy_qmp *phy = platform_get_drvdata(pdev); if (!phy) return 0; usb_remove_phy(&phy->phy); msm_ssusb_qmp_ldo_enable(phy, 0); regulator_disable(phy->vdd); msm_ssusb_qmp_config_vdd(phy, 0); clk_disable_unprepare(phy->aux_clk); clk_disable_unprepare(phy->cfg_ahb_clk); clk_disable_unprepare(phy->pipe_clk); kfree(phy); return 0; }
static int msm_ssphy_qmp_probe(struct platform_device *pdev) { struct msm_ssphy_qmp *phy; struct device *dev = &pdev->dev; struct resource *res; int ret = 0; phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); if (!phy) return -ENOMEM; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qmp_phy_base"); phy->base = devm_ioremap_resource(dev, res); if (IS_ERR(phy->base)) return PTR_ERR(phy->base); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qmp_ahb2phy_base"); phy->ahb2phy = devm_ioremap_resource(dev, res); if (IS_ERR(phy->ahb2phy)) { dev_err(dev, "couldn't find qmp_ahb2phy_base address.\n"); return PTR_ERR(phy->ahb2phy); } ret = of_property_read_u32_array(dev->of_node, "qcom,vdd-voltage-level", (u32 *) phy->vdd_levels, ARRAY_SIZE(phy->vdd_levels)); if (ret) { dev_err(dev, "error reading qcom,vdd-voltage-level property\n"); return ret; } phy->vdd = devm_regulator_get(dev, "vdd"); if (IS_ERR(phy->vdd)) { dev_err(dev, "unable to get vdd supply\n"); return PTR_ERR(phy->vdd); } phy->vdda18 = devm_regulator_get(dev, "vdda18"); if (IS_ERR(phy->vdda18)) { dev_err(dev, "unable to get vdda18 supply\n"); return PTR_ERR(phy->vdda18); } ret = msm_ssusb_qmp_config_vdd(phy, 1); if (ret) { dev_err(dev, "ssusb vdd_dig configuration failed\n"); return ret; } ret = regulator_enable(phy->vdd); if (ret) { dev_err(dev, "unable to enable the ssusb vdd_dig\n"); goto unconfig_ss_vdd; } ret = msm_ssusb_qmp_ldo_enable(phy, 1); if (ret) { dev_err(dev, "ssusb vreg enable failed\n"); goto disable_ss_vdd; } phy->ldo_clk = devm_clk_get(dev, "ldo_clk"); if (!IS_ERR(phy->ldo_clk)) clk_prepare_enable(phy->ldo_clk); platform_set_drvdata(pdev, phy); if (of_property_read_bool(dev->of_node, "qcom,vbus-valid-override")) phy->phy.flags |= PHY_VBUS_VALID_OVERRIDE; phy->override_pll_cal = of_property_read_bool(dev->of_node, "qcom,override-pll-calibration"); if (phy->override_pll_cal) dev_dbg(dev, "Override PHY PLL calibration is enabled.\n"); phy->switch_pipe_clk_src = !of_property_read_bool(dev->of_node, "qcom,no-pipe-clk-switch"); phy->phy.dev = dev; phy->phy.init = msm_ssphy_qmp_init; phy->phy.set_suspend = msm_ssphy_qmp_set_suspend; phy->phy.set_params = msm_ssphy_qmp_set_params; phy->phy.notify_connect = msm_ssphy_qmp_notify_connect; phy->phy.notify_disconnect = msm_ssphy_qmp_notify_disconnect; phy->phy.reset = msm_ssphy_qmp_reset; phy->phy.type = USB_PHY_TYPE_USB3; ret = usb_add_phy_dev(&phy->phy); if (ret) goto disable_ss_ldo; return 0; disable_ss_ldo: if (!IS_ERR(phy->ldo_clk)) clk_disable_unprepare(phy->ldo_clk); msm_ssusb_qmp_ldo_enable(phy, 0); disable_ss_vdd: regulator_disable(phy->vdd); unconfig_ss_vdd: msm_ssusb_qmp_config_vdd(phy, 0); return ret; }
static int msm_ssphy_qmp_probe(struct platform_device *pdev) { struct msm_ssphy_qmp *phy; struct device *dev = &pdev->dev; struct resource *res; int ret = 0; phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); if (!phy) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "missing memory base resource\n"); return -ENODEV; } phy->base = devm_ioremap_nocache(dev, res->start, resource_size(res)); if (!phy->base) { dev_err(dev, "ioremap failed\n"); return -ENODEV; } ret = of_property_read_u32_array(dev->of_node, "qcom,vdd-voltage-level", (u32 *) phy->vdd_levels, ARRAY_SIZE(phy->vdd_levels)); if (ret) { dev_err(dev, "error reading qcom,vdd-voltage-level property\n"); return ret; } phy->vdd = devm_regulator_get(dev, "vdd"); if (IS_ERR(phy->vdd)) { dev_err(dev, "unable to get vdd supply\n"); return PTR_ERR(phy->vdd); } phy->vdda18 = devm_regulator_get(dev, "vdda18"); if (IS_ERR(phy->vdda18)) { dev_err(dev, "unable to get vdda18 supply\n"); return PTR_ERR(phy->vdda18); } ret = msm_ssusb_qmp_config_vdd(phy, 1); if (ret) { dev_err(dev, "ssusb vdd_dig configuration failed\n"); return ret; } ret = regulator_enable(phy->vdd); if (ret) { dev_err(dev, "unable to enable the ssusb vdd_dig\n"); goto unconfig_ss_vdd; } ret = msm_ssusb_qmp_ldo_enable(phy, 1); if (ret) { dev_err(dev, "ssusb vreg enable failed\n"); goto disable_ss_vdd; } platform_set_drvdata(pdev, phy); if (of_property_read_bool(dev->of_node, "qcom,vbus-valid-override")) phy->phy.flags |= PHY_VBUS_VALID_OVERRIDE; phy->phy.dev = dev; phy->phy.init = msm_ssphy_qmp_init; phy->phy.set_suspend = msm_ssphy_qmp_set_suspend; phy->phy.set_params = msm_ssphy_qmp_set_params; phy->phy.notify_connect = msm_ssphy_qmp_notify_connect; phy->phy.notify_disconnect = msm_ssphy_qmp_notify_disconnect; phy->phy.reset = msm_ssphy_qmp_reset; phy->phy.type = USB_PHY_TYPE_USB3; ret = msm_ssphy_qmp_init_clocks(phy); if (ret) { dev_err(dev, "Fail to init qmp phy clocks\n"); goto disable_ss_ldo; } ret = usb_add_phy_dev(&phy->phy); if (ret) goto disable_ss_ldo; return 0; disable_ss_ldo: msm_ssusb_qmp_ldo_enable(phy, 0); disable_ss_vdd: regulator_disable(phy->vdd); unconfig_ss_vdd: msm_ssusb_qmp_config_vdd(phy, 0); return ret; }