From 25748c0e0144ac4f89c4f1d4592bff66a03c484c Mon Sep 17 00:00:00 2001 From: Meng Dongyang Date: Mon, 24 Oct 2016 17:19:18 +0800 Subject: [PATCH] phy: phy-rockchip-typec: fix usb connect failed after diconnect dp In 4 lane dp mode, the dwc3 controller need to config to usb2.0 only mode, while the dwc3 controller must finish config between usb3.0 and usb2.0 only mode, otherwise if will be failed when connect with usb device. In current code, the config process is done in typec phy init function, and is called durling dwc3 controller init, so it is too late for dwc3 controller to config. This patch config usb2.0 only mode when usb phy power on and config to usb3.0 when usb phy power off if it is dp mode only. Finish change to usb3.0 before dwc3 controller reinit to usb3.0 mode. Change-Id: Iad69dc730408a88bb5f3b9d9bd366754f82db182 Signed-off-by: Meng Dongyang --- drivers/phy/phy-rockchip-typec.c | 35 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/phy/phy-rockchip-typec.c b/drivers/phy/phy-rockchip-typec.c index d8b80dfc3eae..9599cb7ff4ca 100644 --- a/drivers/phy/phy-rockchip-typec.c +++ b/drivers/phy/phy-rockchip-typec.c @@ -561,28 +561,12 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode) tcphy_cfg_24m(tcphy); if (mode == MODE_DFP_DP) { - /* - * Config usb work in USB2.0 only mode, we need to ensure - * usb3 pd is enabled before access these regiters. - */ - property_enable(tcphy, &cfg->usb3tousb2_en, 1); - property_enable(tcphy, &cfg->usb3host_disable, 1); - property_enable(tcphy, &cfg->usb3host_port, 0); - tcphy_cfg_dp_pll(tcphy); for (i = 0; i < 4; i++) tcphy_dp_cfg_lane(tcphy, i); writel(PIN_ASSIGN_C_E, tcphy->base + PMA_LANE_CFG); } else { - /* - * Enable usb work in usb3.0, we need to ensure usb3 - * pd is enabled before access these registers. - */ - property_enable(tcphy, &cfg->usb3tousb2_en, 0); - property_enable(tcphy, &cfg->usb3host_disable, 0); - property_enable(tcphy, &cfg->usb3host_port, 1); - tcphy_cfg_usb3_pll(tcphy); tcphy_cfg_dp_pll(tcphy); if (tcphy->flip) { @@ -688,6 +672,18 @@ static int tcphy_get_mode(struct rockchip_typec_phy *tcphy) return mode; } +static int tcphy_cfg_usb3_to_usb2_only(struct rockchip_typec_phy *tcphy, + bool value) +{ + struct rockchip_usb3phy_port_cfg *cfg = &tcphy->port_cfgs; + + property_enable(tcphy, &cfg->usb3tousb2_en, value); + property_enable(tcphy, &cfg->usb3host_disable, value); + property_enable(tcphy, &cfg->usb3host_port, !value); + + return 0; +} + static int rockchip_usb3_phy_power_on(struct phy *phy) { struct rockchip_typec_phy *tcphy = phy_get_drvdata(phy); @@ -705,8 +701,10 @@ static int rockchip_usb3_phy_power_on(struct phy *phy) } /* DP-only mode; fall back to USB2 */ - if (!(new_mode & (MODE_DFP_USB | MODE_UFP_USB))) + if (!(new_mode & (MODE_DFP_USB | MODE_UFP_USB))) { + tcphy_cfg_usb3_to_usb2_only(tcphy, true); goto unlock_ret; + } if (tcphy->mode == new_mode) goto unlock_ret; @@ -740,6 +738,9 @@ static int rockchip_usb3_phy_power_off(struct phy *phy) mutex_lock(&tcphy->lock); + if (!(tcphy->mode & (MODE_UFP_USB | MODE_DFP_USB))) + tcphy_cfg_usb3_to_usb2_only(tcphy, false); + if (tcphy->mode == MODE_DISCONNECT) goto unlock; -- 2.34.1