Merge tag 'u-boot-imx-20211020' of https://source.denx.de/u-boot/custodians/u-boot-imx
[platform/kernel/u-boot.git] / drivers / phy / phy-stm32-usbphyc.c
index 464b073..9c1dcfa 100644 (file)
@@ -3,6 +3,8 @@
  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
  */
 
+#define LOG_CATEGORY UCLASS_PHY
+
 #include <common.h>
 #include <clk.h>
 #include <div64.h>
@@ -59,6 +61,7 @@ struct stm32_usbphyc {
        struct udevice *vdda1v8;
        struct stm32_usbphyc_phy {
                struct udevice *vdd;
+               struct udevice *vbus;
                bool init;
                bool powered;
        } phys[MAX_PHYS];
@@ -97,8 +100,8 @@ static int stm32_usbphyc_pll_init(struct stm32_usbphyc *usbphyc)
        u32 usbphyc_pll;
 
        if ((clk_rate < PLL_INFF_MIN_RATE) || (clk_rate > PLL_INFF_MAX_RATE)) {
-               pr_debug("%s: input clk freq (%dHz) out of range\n",
-                        __func__, clk_rate);
+               log_debug("input clk freq (%dHz) out of range\n",
+                         clk_rate);
                return -EINVAL;
        }
 
@@ -115,8 +118,8 @@ static int stm32_usbphyc_pll_init(struct stm32_usbphyc *usbphyc)
 
        writel(usbphyc_pll, usbphyc->base + STM32_USBPHYC_PLL);
 
-       pr_debug("%s: input clk freq=%dHz, ndiv=%d, frac=%d\n", __func__,
-                clk_rate, pll_params.ndiv, pll_params.frac);
+       log_debug("input clk freq=%dHz, ndiv=%d, frac=%d\n",
+                 clk_rate, pll_params.ndiv, pll_params.frac);
 
        return 0;
 }
@@ -153,7 +156,7 @@ static int stm32_usbphyc_phy_init(struct phy *phy)
                     true : false;
        int ret;
 
-       pr_debug("%s phy ID = %lu\n", __func__, phy->id);
+       dev_dbg(phy->dev, "phy ID = %lu\n", phy->id);
        /* Check if one phy port has already configured the pll */
        if (pllen && stm32_usbphyc_is_init(usbphyc))
                goto initialized;
@@ -199,7 +202,7 @@ static int stm32_usbphyc_phy_exit(struct phy *phy)
        struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + phy->id;
        int ret;
 
-       pr_debug("%s phy ID = %lu\n", __func__, phy->id);
+       dev_dbg(phy->dev, "phy ID = %lu\n", phy->id);
        usbphyc_phy->init = false;
 
        /* Check if other phy port requires pllen */
@@ -238,12 +241,17 @@ static int stm32_usbphyc_phy_power_on(struct phy *phy)
        struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + phy->id;
        int ret;
 
-       pr_debug("%s phy ID = %lu\n", __func__, phy->id);
+       dev_dbg(phy->dev, "phy ID = %lu\n", phy->id);
        if (usbphyc_phy->vdd) {
                ret = regulator_set_enable(usbphyc_phy->vdd, true);
                if (ret)
                        return ret;
        }
+       if (usbphyc_phy->vbus) {
+               ret = regulator_set_enable(usbphyc_phy->vbus, true);
+               if (ret)
+                       return ret;
+       }
 
        usbphyc_phy->powered = true;
 
@@ -256,14 +264,19 @@ static int stm32_usbphyc_phy_power_off(struct phy *phy)
        struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + phy->id;
        int ret;
 
-       pr_debug("%s phy ID = %lu\n", __func__, phy->id);
+       dev_dbg(phy->dev, "phy ID = %lu\n", phy->id);
        usbphyc_phy->powered = false;
 
        if (stm32_usbphyc_is_powered(usbphyc))
                return 0;
 
+       if (usbphyc_phy->vbus) {
+               ret = regulator_set_enable(usbphyc_phy->vbus, false);
+               if (ret)
+                       return ret;
+       }
        if (usbphyc_phy->vdd) {
-               ret = regulator_set_enable(usbphyc_phy->vdd, false);
+               ret = regulator_set_enable_if_allowed(usbphyc_phy->vdd, false);
                if (ret)
                        return ret;
        }
@@ -271,7 +284,7 @@ static int stm32_usbphyc_phy_power_off(struct phy *phy)
        return 0;
 }
 
-static int stm32_usbphyc_get_regulator(struct udevice *dev, ofnode node,
+static int stm32_usbphyc_get_regulator(ofnode node,
                                       char *supply_name,
                                       struct udevice **regulator)
 {
@@ -281,19 +294,14 @@ static int stm32_usbphyc_get_regulator(struct udevice *dev, ofnode node,
        ret = ofnode_parse_phandle_with_args(node, supply_name,
                                             NULL, 0, 0,
                                             &regulator_phandle);
-       if (ret) {
-               dev_err(dev, "Can't find %s property (%d)\n", supply_name, ret);
+       if (ret)
                return ret;
-       }
 
        ret = uclass_get_device_by_ofnode(UCLASS_REGULATOR,
                                          regulator_phandle.node,
                                          regulator);
-
-       if (ret) {
-               dev_err(dev, "Can't get %s regulator (%d)\n", supply_name, ret);
+       if (ret)
                return ret;
-       }
 
        return 0;
 }
@@ -311,7 +319,7 @@ static int stm32_usbphyc_of_xlate(struct phy *phy,
 
        if ((phy->id == 0 && args->args_count != 1) ||
            (phy->id == 1 && args->args_count != 2)) {
-               dev_err(dev, "invalid number of cells for phy port%ld\n",
+               dev_err(phy->dev, "invalid number of cells for phy port%ld\n",
                        phy->id);
                return -EINVAL;
        }
@@ -331,8 +339,8 @@ static int stm32_usbphyc_probe(struct udevice *dev)
 {
        struct stm32_usbphyc *usbphyc = dev_get_priv(dev);
        struct reset_ctl reset;
-       ofnode node;
-       int i, ret;
+       ofnode node, connector;
+       int ret;
 
        usbphyc->base = dev_read_addr(dev);
        if (usbphyc->base == FDT_ADDR_T_NONE)
@@ -370,22 +378,33 @@ static int stm32_usbphyc_probe(struct udevice *dev)
                return ret;
        }
 
-       /*
-        * parse all PHY subnodes in order to populate regulator associated
-        * to each PHY port
-        */
-       node = dev_read_first_subnode(dev);
-       for (i = 0; i < MAX_PHYS; i++) {
-               struct stm32_usbphyc_phy *usbphyc_phy = usbphyc->phys + i;
-
+       /* parse all PHY subnodes to populate regulator associated to each PHY port */
+       dev_for_each_subnode(node, dev) {
+               fdt_addr_t phy_id;
+               struct stm32_usbphyc_phy *usbphyc_phy;
+
+               phy_id = ofnode_read_u32_default(node, "reg", FDT_ADDR_T_NONE);
+               if (phy_id >= MAX_PHYS) {
+                       dev_err(dev, "invalid reg value %lx for %s\n",
+                               phy_id, ofnode_get_name(node));
+                       return -ENOENT;
+               }
+               usbphyc_phy = usbphyc->phys + phy_id;
                usbphyc_phy->init = false;
                usbphyc_phy->powered = false;
-               ret = stm32_usbphyc_get_regulator(dev, node, "phy-supply",
+               ret = stm32_usbphyc_get_regulator(node, "phy-supply",
                                                  &usbphyc_phy->vdd);
-               if (ret)
+               if (ret) {
+                       dev_err(dev, "Can't get phy-supply regulator\n");
                        return ret;
-
-               node = dev_read_next_subnode(node);
+               }
+
+               usbphyc_phy->vbus = NULL;
+               connector = ofnode_find_subnode(node, "connector");
+               if (ofnode_valid(connector)) {
+                       ret = stm32_usbphyc_get_regulator(connector, "vbus-supply",
+                                                         &usbphyc_phy->vbus);
+               }
        }
 
        /* Check if second port has to be used for host controller */
@@ -406,5 +425,5 @@ U_BOOT_DRIVER(stm32_usb_phyc) = {
        .of_match = stm32_usbphyc_of_match,
        .ops = &stm32_usbphyc_phy_ops,
        .probe = stm32_usbphyc_probe,
-       .priv_auto_alloc_size = sizeof(struct stm32_usbphyc),
+       .priv_auto      = sizeof(struct stm32_usbphyc),
 };