phy: phy-rockchip-inno-usb2: add reset support
authorSebastian Reichel <sebastian.reichel@collabora.com>
Mon, 22 May 2023 17:03:20 +0000 (19:03 +0200)
committerVinod Koul <vkoul@kernel.org>
Wed, 12 Jul 2023 16:57:41 +0000 (22:27 +0530)
Add reset handling support, which is needed for proper
operation with RK3588.

Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Link: https://lore.kernel.org/r/20230522170324.61349-4-sebastian.reichel@collabora.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/phy/rockchip/phy-rockchip-inno-usb2.c

index 2c4683c..101b469 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
 #include <linux/regmap.h>
+#include <linux/reset.h>
 #include <linux/mfd/syscon.h>
 #include <linux/usb/of.h>
 #include <linux/usb/otg.h>
@@ -223,6 +224,7 @@ struct rockchip_usb2phy_port {
  * @clk: clock struct of phy input clk.
  * @clk480m: clock struct of phy output clk.
  * @clk480m_hw: clock struct of phy output clk management.
+ * @phy_reset: phy reset control.
  * @chg_state: states involved in USB charger detection.
  * @chg_type: USB charger types.
  * @dcd_retries: The retry count used to track Data contact
@@ -239,6 +241,7 @@ struct rockchip_usb2phy {
        struct clk      *clk;
        struct clk      *clk480m;
        struct clk_hw   clk480m_hw;
+       struct reset_control    *phy_reset;
        enum usb_chg_state      chg_state;
        enum power_supply_type  chg_type;
        u8                      dcd_retries;
@@ -280,6 +283,25 @@ static inline bool property_enabled(struct regmap *base,
        return tmp != reg->disable;
 }
 
+static int rockchip_usb2phy_reset(struct rockchip_usb2phy *rphy)
+{
+       int ret;
+
+       ret = reset_control_assert(rphy->phy_reset);
+       if (ret)
+               return ret;
+
+       udelay(10);
+
+       ret = reset_control_deassert(rphy->phy_reset);
+       if (ret)
+               return ret;
+
+       usleep_range(100, 200);
+
+       return 0;
+}
+
 static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
 {
        struct rockchip_usb2phy *rphy =
@@ -534,6 +556,18 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
                return ret;
        }
 
+       /*
+        * For rk3588, it needs to reset phy when exit from
+        * suspend mode with common_on_n 1'b1(aka REFCLK_LOGIC,
+        * Bias, and PLL blocks are powered down) for lower
+        * power consumption. If you don't want to reset phy,
+        * please keep the common_on_n 1'b0 to set these blocks
+        * remain powered.
+        */
+       ret = rockchip_usb2phy_reset(rphy);
+       if (ret)
+               return ret;
+
        /* waiting for the utmi_clk to become stable */
        usleep_range(1500, 2000);
 
@@ -1348,6 +1382,10 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
+       rphy->phy_reset = devm_reset_control_get_optional(dev, "phy");
+       if (IS_ERR(rphy->phy_reset))
+               return PTR_ERR(rphy->phy_reset);
+
        rphy->clk = of_clk_get_by_name(np, "phyclk");
        if (!IS_ERR(rphy->clk)) {
                clk_prepare_enable(rphy->clk);