[PATCH] phy: rockchip: inno-usb2: fix hang when multiple controllers exit

Siva Mahadevan me at svmhdvn.name
Sat Oct 23 19:23:32 CEST 2021


Icenowy Zheng wrote:
> The OHCI and EHCI controllers are both bound to the same PHY. They will
> both do init and power_on operations when the controller is brought up
> and both do power_off and exit when the controller is stopped. However,
> the PHY uclass of U-Boot is not as sane as we thought -- they won't
> maintain a status mark for PHYs, and thus the functions of the PHYs
> could be called for multiple times. Calling init/power_on for multiple
> times have no severe problems, however calling power_off/exit for
> multiple times have a problem -- the first exit call will stop the PHY
> clock, and power_off/exit calls after it still trying to write to PHY
> registers. The write operation to PHY registers will fail because clock
> is already stopped.
> 
> Adapt the count mechanism from phy-sun4i-usb to both init/exit and
> power_on/power_off functions to phy-rockchip-inno-usb2 to fix this
> problem. With this stopping USB controllers (manually or before booting
> a kernel) will work.
> 
> Signed-off-by: Icenowy Zheng <icenowy at aosc.io>
> Fixes: ac97a9ece14e ("phy: rockchip: Add Rockchip USB2PHY driver")
> ---
>  drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 21 +++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 
> diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
> index 62b8ba3a4a..be9cc99d90 100644
> --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
> +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
> @@ -62,6 +62,8 @@ struct rockchip_usb2phy {
>  	void *reg_base;
>  	struct clk phyclk;
>  	const struct rockchip_usb2phy_cfg *phy_cfg;
> +	int init_count;
> +	int power_on_count;
>  };
>  
>  static inline int property_enable(void *reg_base,
> @@ -92,6 +94,10 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
>  	struct rockchip_usb2phy *priv = dev_get_priv(parent);
>  	const struct rockchip_usb2phy_port_cfg *port_cfg = us2phy_get_port(phy);
>  
> +	priv->power_on_count++;
> +	if (priv->power_on_count != 1)
> +		return 0;
> +
>  	property_enable(priv->reg_base, &port_cfg->phy_sus, false);
>  
>  	/* waiting for the utmi_clk to become stable */
> @@ -106,6 +112,10 @@ static int rockchip_usb2phy_power_off(struct phy *phy)
>  	struct rockchip_usb2phy *priv = dev_get_priv(parent);
>  	const struct rockchip_usb2phy_port_cfg *port_cfg = us2phy_get_port(phy);
>  
> +	priv->power_on_count--;
> +	if (priv->power_on_count != 0)
> +		return 0;
> +
>  	property_enable(priv->reg_base, &port_cfg->phy_sus, true);
>  
>  	return 0;
> @@ -118,6 +128,10 @@ static int rockchip_usb2phy_init(struct phy *phy)
>  	const struct rockchip_usb2phy_port_cfg *port_cfg = us2phy_get_port(phy);
>  	int ret;
>  
> +	priv->init_count++;
> +	if (priv->init_count != 1)
> +		return 0;
> +
>  	ret = clk_enable(&priv->phyclk);
>  	if (ret) {
>  		dev_err(phy->dev, "failed to enable phyclk (ret=%d)\n", ret);
> @@ -140,6 +154,10 @@ static int rockchip_usb2phy_exit(struct phy *phy)
>  	struct udevice *parent = dev_get_parent(phy->dev);
>  	struct rockchip_usb2phy *priv = dev_get_priv(parent);
>  
> +	priv->init_count--;
> +	if (priv->init_count != 0)
> +		return 0;
> +
>  	clk_disable(&priv->phyclk);
>  
>  	return 0;
> @@ -212,6 +230,9 @@ static int rockchip_usb2phy_probe(struct udevice *dev)
>  		return ret;
>  	}
>  
> +	priv->power_on_count = 0;
> +	priv->init_count = 0;
> +
>  	return 0;
>  }
>  
> -- 
> 2.30.2

Are there any plans of submitting this patch to u-boot mainline? I
recently got a pinebook pro and got u-boot mainline working as-is plus
this patch. I can confirm that this fixes the issue for me.


More information about the U-Boot mailing list