From 00168bb5b5aa3802cef7e3b7e44c87ab6bfe9920 Mon Sep 17 00:00:00 2001 From: William Wu Date: Mon, 16 May 2022 12:07:43 +0800 Subject: [PATCH] phy: rockchip: inno-usb2: fix otg port with vbus always on The otg port on Rockchip platforms can be designed in three different hardware circuits with Type-A interface. 1. RK3588 EVB2 Type-A OTG0 port with vbus is controlled by gpio, and vbus is always in high level. 2. RV1106 EVB1 Type-A OTG port with standard vbus designed that vbus isn't always on, and just depends on the OTG mode, that is, when the OTG port work as device mode, the vbus is supplied by Host, when the OTG port work as host mode, the vbus is always on. 3. RV1103 EVB1 Type-A OTG port has no vbus pin, and we set the utmi_bvalid of phy to high from GRF software control. In this case, the utmi_bvalid status register is in low level, so we can't use the utmi_bvalid status to check the utmi_bvalid for RV1103. In order to support the above three application scenarios for Type-A OTG port, especially phy runtime suspend control for device mode, we need this patch. With this patch, we can fix the following two issues: 1. RV1106 EVB1 Type-A OTG port can't enter phy suspend if no usb cable connected. 2. RV1103 failed to switch to device mode by "otg_mode" node, because phy enter suspend unexpectedly. Signed-off-by: William Wu Change-Id: Ia0d388345a4768a721a7e289956bca9684f69a36 --- drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index d60df660682d..ef2c154e402f 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -954,7 +954,8 @@ static int rockchip_usb2phy_set_mode(struct phy *phy, rockchip_set_vbus_power(rport, false); extcon_set_state_sync(rphy->edev, EXTCON_USB_VBUS_EN, false); /* For vbus always on, set EXTCON_USB to true. */ - extcon_set_state(rphy->edev, EXTCON_USB, true); + if (rport->vbus_always_on) + extcon_set_state(rphy->edev, EXTCON_USB, true); rport->perip_connected = true; vbus_det_en = true; break; @@ -969,7 +970,8 @@ static int rockchip_usb2phy_set_mode(struct phy *phy, extcon_set_state_sync(rphy->edev, EXTCON_USB_VBUS_EN, true); /* For vbus always on, deinit EXTCON_USB to false. */ - extcon_set_state(rphy->edev, EXTCON_USB, false); + if (rport->vbus_always_on) + extcon_set_state(rphy->edev, EXTCON_USB, false); rport->perip_connected = false; fallthrough; case PHY_MODE_INVALID: @@ -2092,10 +2094,6 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy, return ret; } - if (rport->vbus_always_on || rport->mode == USB_DR_MODE_HOST || - rport->mode == USB_DR_MODE_UNKNOWN) - goto out; - /* * Set the utmi bvalid come from the usb phy or grf. * For most of Rockchip SoCs, them have VBUSDET pin @@ -2113,6 +2111,13 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy, property_enable(base, &rport->port_cfg->bvalid_grf_sel, false); } + if (rport->vbus_always_on) + extcon_set_state(rphy->edev, EXTCON_USB, true); + + if (rport->vbus_always_on || rport->mode == USB_DR_MODE_HOST || + rport->mode == USB_DR_MODE_UNKNOWN) + goto out; + wake_lock_init(&rport->wakelock, WAKE_LOCK_SUSPEND, "rockchip_otg"); INIT_DELAYED_WORK(&rport->bypass_uart_work, rockchip_usb_bypass_uart_work);