From c90729c46348cbc90d510708c407c8b783c970a9 Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Thu, 13 Jul 2023 11:56:07 -0700 Subject: [PATCH] phy: phy-imx8mq-usb: add vbus regulator support Add support for enabling and disabling vbus-supply regulator found on several imx8mp boards in the usb3_phy0 and usb3_phy1 nodes. Signed-off-by: Tim Harvey Reviewed-by: Adam Ford Reviewed-by: Marek Vasut Tested-by: Marcel Ziswiler --- drivers/phy/phy-imx8mq-usb.c | 39 +++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/drivers/phy/phy-imx8mq-usb.c b/drivers/phy/phy-imx8mq-usb.c index 69f01de555..9fa78ef4da 100644 --- a/drivers/phy/phy-imx8mq-usb.c +++ b/drivers/phy/phy-imx8mq-usb.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #define PHY_CTRL0 0x0 #define PHY_CTRL0_REF_SSP_EN BIT(2) @@ -81,6 +83,7 @@ struct imx8mq_usb_phy { #endif void __iomem *base; enum imx8mpq_phy_type type; + struct udevice *vbus_supply; }; static const struct udevice_id imx8mq_usb_phy_of_match[] = { @@ -173,9 +176,9 @@ static int imx8mq_usb_phy_power_on(struct phy *usb_phy) struct udevice *dev = usb_phy->dev; struct imx8mq_usb_phy *imx_phy = dev_get_priv(dev); u32 value; + int ret; #if CONFIG_IS_ENABLED(CLK) - int ret; ret = clk_enable(&imx_phy->phy_clk); if (ret) { printf("Failed to enable usb phy clock\n"); @@ -183,12 +186,26 @@ static int imx8mq_usb_phy_power_on(struct phy *usb_phy) } #endif + if (CONFIG_IS_ENABLED(DM_REGULATOR) && imx_phy->vbus_supply) { + ret = regulator_set_enable_if_allowed(imx_phy->vbus_supply, true); + if (ret && ret != -ENOSYS) { + dev_err(dev, "Failed to enable VBUS regulator: %d\n", ret); + goto err; + } + } + /* Disable rx term override */ value = readl(imx_phy->base + PHY_CTRL6); value &= ~PHY_CTRL6_RXTERM_OVERRIDE_SEL; writel(value, imx_phy->base + PHY_CTRL6); return 0; + +err: +#if CONFIG_IS_ENABLED(CLK) + clk_disable(&imx_phy->phy_clk); +#endif + return ret; } static int imx8mq_usb_phy_power_off(struct phy *usb_phy) @@ -196,6 +213,7 @@ static int imx8mq_usb_phy_power_off(struct phy *usb_phy) struct udevice *dev = usb_phy->dev; struct imx8mq_usb_phy *imx_phy = dev_get_priv(dev); u32 value; + int ret; /* Override rx term to be 0 */ value = readl(imx_phy->base + PHY_CTRL6); @@ -206,6 +224,14 @@ static int imx8mq_usb_phy_power_off(struct phy *usb_phy) clk_disable(&imx_phy->phy_clk); #endif + if (CONFIG_IS_ENABLED(DM_REGULATOR) && imx_phy->vbus_supply) { + ret = regulator_set_enable_if_allowed(imx_phy->vbus_supply, false); + if (ret && ret != -ENOSYS) { + dev_err(dev, "Failed to disable VBUS regulator: %d\n", ret); + return ret; + } + } + return 0; } @@ -224,6 +250,7 @@ struct phy_ops imx8mq_usb_phy_ops = { int imx8mq_usb_phy_probe(struct udevice *dev) { struct imx8mq_usb_phy *priv = dev_get_priv(dev); + int ret; priv->type = dev_get_driver_data(dev); priv->base = dev_read_addr_ptr(dev); @@ -232,8 +259,6 @@ int imx8mq_usb_phy_probe(struct udevice *dev) return -EINVAL; #if CONFIG_IS_ENABLED(CLK) - int ret; - /* Assigned clock already set clock */ ret = clk_get_by_name(dev, "phy", &priv->phy_clk); if (ret) { @@ -241,6 +266,14 @@ int imx8mq_usb_phy_probe(struct udevice *dev) return ret; } #endif + if (CONFIG_IS_ENABLED(DM_REGULATOR)) { + ret = device_get_supply_regulator(dev, "vbus-supply", + &priv->vbus_supply); + if (ret && ret != -ENOENT) { + dev_err(dev, "Failed to get VBUS regulator: %d\n", ret); + return ret; + } + } return 0; } -- 2.39.5