[PATCH v13 35/35] phy: rockchip: usbdp: Add USB-C state without DP enabled
From: Sebastian Reichel <hidden>
Date: 2026-07-14 19:26:22
Also in:
linux-devicetree, linux-phy, linux-rockchip, linux-usb, lkml
Subsystem:
arm/rockchip soc support, generic phy framework, the rest · Maintainers:
Heiko Stuebner, Vinod Koul, Linus Torvalds
The driver currently only differs between 4 lanes DP mode or combined DP + USB3 mode. This makes sense from a lane routing point of view, as the hardware only has 2 lanes of USB3. But adding a separate state for USB-only helps with power management, since we always power up all PHY parts according to the current hardware setup to avoid data stream interruptions. Even if some lanes are muxed to the DP controller there is no need to keep the DP side enabled if something without DP AltMode is plugged into USB-C. This potentially triggers some more USB reconnections during the PD AltMode negotiation when switching from USB-only to combined USB+DP mode. This should be fine, as the cable is freshly plugged at this point. Signed-off-by: Sebastian Reichel <redacted> --- drivers/phy/rockchip/phy-rockchip-usbdp.c | 57 ++++++++++++++++++------------- 1 file changed, 33 insertions(+), 24 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 87d6df682176..ef6fdf3d02bd 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c@@ -580,32 +580,14 @@ static void rk_udphy_dp_lane_enable(struct rk_udphy *udphy, int dp_lanes) CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0)); } -static void rk_udphy_mode_set(struct rk_udphy *udphy, u8 hw_mode) +static void rk_udphy_set_lane_mux(struct rk_udphy *udphy) { - if (udphy->hw_mode == hw_mode) - return; - - udphy->phy_needs_reinit = true; - udphy->hw_mode = hw_mode; -} - -static void rk_udphy_set_typec_state(struct rk_udphy *udphy, unsigned long state) -{ - u8 hw_mode; - - switch (state) { - case TYPEC_DP_STATE_C: - case TYPEC_DP_STATE_E: + if (udphy->dp_lanes == 4) { udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; - hw_mode = UDPHY_MODE_DP; - udphy->dp_lanes = 4; - break; - - case TYPEC_DP_STATE_D: - default: + } else { if (udphy->flip) { udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP;
@@ -617,12 +599,39 @@ static void rk_udphy_set_typec_state(struct rk_udphy *udphy, unsigned long state udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; } - hw_mode = UDPHY_MODE_DP_USB; - udphy->dp_lanes = 2; + } +} + +static void rk_udphy_mode_set(struct rk_udphy *udphy, u8 hw_mode, u8 dp_lanes) +{ + if (udphy->hw_mode == hw_mode && udphy->dp_lanes == dp_lanes) + return; + + udphy->phy_needs_reinit = true; + udphy->hw_mode = hw_mode; + udphy->dp_lanes = dp_lanes; +} + +static void rk_udphy_set_typec_state(struct rk_udphy *udphy, unsigned long state) +{ + switch (state) { + case TYPEC_DP_STATE_C: + case TYPEC_DP_STATE_E: + rk_udphy_mode_set(udphy, UDPHY_MODE_DP, 4); + break; + + case TYPEC_DP_STATE_D: + rk_udphy_mode_set(udphy, UDPHY_MODE_DP_USB, 2); + break; + + case TYPEC_STATE_SAFE: + case TYPEC_STATE_USB: + default: + rk_udphy_mode_set(udphy, UDPHY_MODE_USB, 0); break; } - rk_udphy_mode_set(udphy, hw_mode); + rk_udphy_set_lane_mux(udphy); } static void rk_udphy_set_typec_default_mapping(struct rk_udphy *udphy)
--
2.53.0