All of lore.kernel.org
 help / color / mirror / Atom feed
From: Icenowy Zheng <icenowy@aosc.io>
To: u-boot@lists.denx.de
Subject: [PATCH] phy: rockchip: inno-usb2: fix hang when multiple controllers exit
Date: Wed, 07 Apr 2021 14:43:56 +0800	[thread overview]
Message-ID: <DCA1928D-C31D-42BF-9D08-45A571079F9A@aosc.io> (raw)
In-Reply-To: <4e48a1c9-fd01-48c8-fc5d-ebdfb626ee42@rock-chips.com>



? 2021?4?7? GMT+08:00 ??2:42:34, Frank Wang <frank.wang@rock-chips.com> ??:
>Hi Icenowy Zheng,
>
>In my view, it is better to implement this mechanism in phy-uclass
>which 
>resemble Linux Kernel have implemented that can avoid do duplication of
>
>work in each SoC's PHY driver.

I'm afraid of breaking existing drivers when implementing it in uclass,
although I agree this will be more clean.

>
>
>BR.
>Frank
>
>On 2021/4/6 23:10, 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@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;
>>   }
>>   

  reply	other threads:[~2021-04-07  6:43 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-06 15:10 [PATCH] phy: rockchip: inno-usb2: fix hang when multiple controllers exit Icenowy Zheng
2021-04-06 23:11 ` Peter Robinson
2021-04-07  6:42 ` Frank Wang
2021-04-07  6:43   ` Icenowy Zheng [this message]
2021-04-07  7:28     ` Frank Wang
2021-04-07  7:31       ` Icenowy Zheng
2021-07-02 12:55         ` Grant Likely
2021-10-23 17:23 ` Siva Mahadevan
2021-10-23 18:19   ` Icenowy Zheng
2021-11-12 22:40     ` Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DCA1928D-C31D-42BF-9D08-45A571079F9A@aosc.io \
    --to=icenowy@aosc.io \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.