From d8db0c1fa4ae5dec6b4e54716fad3b8fc3af2830 Mon Sep 17 00:00:00 2001 From: William Wu Date: Mon, 10 Oct 2022 11:27:24 +0800 Subject: [PATCH] phy: rockchip: inno-usb2: fix phy reset during power on for rk3588 The RK3588 USB2 PHY provides CLK12MOHCI and CLK48MOHCI to OHCI controllers, and the two clocks are turned off upon PHY reset, therefore it shouldn't access OHCI Controller if USB2 PHY in reset. However, during the system PM resume, the current USB2 PHY power on sequence with PHY reset operation has potential risk that reset PHY accidentally when OHCI platform resume access OHCI Controller, and cause system hung. The reason is EHCI/OHCI controllers resume ordering on RK3588. In outline form, the hcd_bus_resume() of EHCI and the ohci_resume() of OHCI operating concurrently on different CPUs perform the following actions: CPU 0 CPU 1 ---------------------------- --------------------------------- async_resume() usb_resume() hcd_bus_resume() -- EHCI usb_phy_roothub_resume() phy_power_on() rockchip_usb2phy_power_on() ohci_platform_resume() rockchip_usb2phy_reset() ohci_resume() assert phy reset ... udelay(10); ohci_readl or ohci_writel This patch fixes USB2 PHY reset during power on for RK3588, only do USB2 PHY reset for RK3588 USB OTG0 and OTG1, because their 'common_on_n' bit can be set to 1'b1 (aka REFCLK_LOGIC, Bias, and PLL blocks are powered down) in PM runtime process. And keep the 'common_on_n' to 1'b0 for RK3588 USB2 HOST0 and HOST1, thus we don't need to do PHY reset during power on for them. This patch doesn't increase the USB2 PHY power consumption, because the USB2 HOST0 and HOST1 don't support PM runtime management, so actually the PHY PLL blocks of USB2 HOST0 and HOST1 are always powered on. Signed-off-by: William Wu Change-Id: Ia0121a7c49bef4f0f3a1fb11a810e4ef95b29982 --- drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 238668ea5394..2b3dec923248 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -853,9 +853,12 @@ static int rockchip_usb2phy_power_on(struct phy *phy) * please keep the common_on_n 1'b0 to set these blocks * remain powered. */ - ret = rockchip_usb2phy_reset(rphy); - if (ret) - goto unlock; + if (rport->port_id == USB2PHY_PORT_OTG && + of_device_is_compatible(rphy->dev->of_node, "rockchip,rk3588-usb2phy")) { + ret = rockchip_usb2phy_reset(rphy); + if (ret) + goto unlock; + } /* waiting for the utmi_clk to become stable */ usleep_range(1500, 2000); @@ -3665,7 +3668,7 @@ static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = { .reg = 0x8000, .num_ports = 1, .phy_tuning = rk3588_usb2phy_tuning, - .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, + .clkout_ctl = { 0x0000, 0, 0, 0, 0 }, .ls_filter_con = { 0x0040, 19, 0, 0x30100, 0x00020 }, .port_cfgs = { [USB2PHY_PORT_HOST] = { @@ -3687,7 +3690,7 @@ static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = { .reg = 0xc000, .num_ports = 1, .phy_tuning = rk3588_usb2phy_tuning, - .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, + .clkout_ctl = { 0x0000, 0, 0, 0, 0 }, .ls_filter_con = { 0x0040, 19, 0, 0x30100, 0x00020 }, .port_cfgs = { [USB2PHY_PORT_HOST] = {