diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 6ee7ef79b4f8..14c1f35a4b10 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -322,33 +322,6 @@ static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) free_dma_aligned_buffer(urb); } -static int setup_vbus_gpio(struct platform_device *pdev, - struct tegra_ehci_platform_data *pdata) -{ - int err = 0; - int gpio; - - gpio = pdata->vbus_gpio; - if (!gpio_is_valid(gpio)) - gpio = of_get_named_gpio(pdev->dev.of_node, - "nvidia,vbus-gpio", 0); - if (!gpio_is_valid(gpio)) - return 0; - - err = gpio_request(gpio, "vbus_gpio"); - if (err) { - dev_err(&pdev->dev, "can't request vbus gpio %d", gpio); - return err; - } - err = gpio_direction_output(gpio, 1); - if (err) { - dev_err(&pdev->dev, "can't enable vbus\n"); - return err; - } - - return err; -} - static int tegra_ehci_probe(struct platform_device *pdev) { struct resource *res; @@ -376,14 +349,11 @@ static int tegra_ehci_probe(struct platform_device *pdev) if (!pdev->dev.coherent_dma_mask) pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); - setup_vbus_gpio(pdev, pdata); - hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { dev_err(&pdev->dev, "Unable to create HCD\n"); - err = -ENOMEM; - goto cleanup_vbus_gpio; + return -ENOMEM; } platform_set_drvdata(pdev, hcd); ehci = hcd_to_ehci(hcd); @@ -494,8 +464,6 @@ static int tegra_ehci_probe(struct platform_device *pdev) clk_put(tegra->clk); cleanup_hcd_create: usb_put_hcd(hcd); -cleanup_vbus_gpio: - /* FIXME: Undo setup_vbus_gpio() here */ return err; } diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index 3ecd49871b88..d92a63a5b0c9 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -34,6 +34,7 @@ #include #include #include +#include #define ULPI_VIEWPORT 0x170 @@ -613,6 +614,9 @@ static void tegra_usb_phy_close(struct usb_phy *x) { struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); + if (!IS_ERR(phy->vbus)) + regulator_disable(phy->vbus); + clk_disable_unprepare(phy->pll_u); } @@ -705,6 +709,16 @@ static int tegra_usb_phy_init(struct tegra_usb_phy *phy) goto fail; } + if (!IS_ERR(phy->vbus)) { + err = regulator_enable(phy->vbus); + if (err) { + dev_err(phy->dev, + "failed to enable usb vbus regulator: %d\n", + err); + goto fail; + } + } + if (phy->is_ulpi_phy) err = ulpi_open(phy); else @@ -896,6 +910,16 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) } else tegra_phy->mode = TEGRA_USB_PHY_MODE_OTG; + /* On some boards, the VBUS regulator doesn't need to be controlled */ + if (of_find_property(np, "vbus-supply", NULL)) { + tegra_phy->vbus = devm_regulator_get(&pdev->dev, "vbus"); + if (IS_ERR(tegra_phy->vbus)) + return PTR_ERR(tegra_phy->vbus); + } else { + dev_notice(&pdev->dev, "no vbus regulator"); + tegra_phy->vbus = ERR_PTR(-ENODEV); + } + tegra_phy->dev = &pdev->dev; err = tegra_usb_phy_init(tegra_phy); if (err < 0) diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h index d2ca919a5b73..2b5fa947980a 100644 --- a/include/linux/usb/tegra_usb_phy.h +++ b/include/linux/usb/tegra_usb_phy.h @@ -55,6 +55,7 @@ struct tegra_usb_phy { struct clk *clk; struct clk *pll_u; struct clk *pad_clk; + struct regulator *vbus; enum tegra_usb_phy_mode mode; void *config; struct usb_phy *ulpi;