]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
phy: rockchip: inno-usb2: fix communication disruption in gadget mode
authorLuca Ceresoli <luca.ceresoli@bootlin.com>
Thu, 27 Nov 2025 10:26:17 +0000 (11:26 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 Jan 2026 10:21:25 +0000 (11:21 +0100)
commit 7d8f725b79e35fa47e42c88716aad8711e1168d8 upstream.

When the OTG USB port is used to power to SoC, configured as peripheral and
used in gadget mode, communication stops without notice about 6 seconds
after the gadget is configured and enumerated.

The problem was observed on a Radxa Rock Pi S board, which can only be
powered by the only USB-C connector. That connector is the only one usable
in gadget mode. This implies the USB cable is connected from before boot
and never disconnects while the kernel runs.

The related code flow in the PHY driver code can be summarized as:

 * the first time chg_detect_work starts (6 seconds after gadget is
   configured and enumerated)
   -> rockchip_chg_detect_work():
       if chg_state is UNDEFINED:
          property_enable(base, &rphy->phy_cfg->chg_det.opmode, false); [Y]

 * rockchip_chg_detect_work() changes state and re-triggers itself a few
   times until it reaches the DETECTED state:
   -> rockchip_chg_detect_work():
       if chg_state is DETECTED:
          property_enable(base, &rphy->phy_cfg->chg_det.opmode, true); [Z]

At [Y] all existing communications stop. E.g. using a CDC serial gadget,
the /dev/tty* devices are still present on both host and device, but no
data is transferred anymore. The later call with a 'true' argument at [Z]
does not restore it.

Due to the lack of documentation, what chg_det.opmode does exactly is not
clear, however by code inspection it seems reasonable that is disables
something needed to keep the communication working, and testing proves that
disabling these lines lets gadget mode keep working. So prevent changes to
chg_det.opmode when there is a cable connected (VBUS present).

Fixes: 98898f3bc83c ("phy: rockchip-inno-usb2: support otg-port for rk3399")
Cc: stable@vger.kernel.org
Closes: https://lore.kernel.org/lkml/20250414185458.7767aabc@booty/
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Reviewed-by: Théo Lebrun <theo.lebrun@bootlin.com>
Link: https://patch.msgid.link/20251127-rk3308-fix-usb-gadget-phy-disconnect-v2-2-dac8a02cd2ca@bootlin.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/phy/rockchip/phy-rockchip-inno-usb2.c

index b0f23690ec3002202c0f33a6988f5509622fa10e..0b5d49b6f7aab7d5b6587f93dad5a3a6b1f99d86 100644 (file)
@@ -831,7 +831,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
                if (!rport->suspended)
                        rockchip_usb2phy_power_off(rport->phy);
                /* put the controller in non-driving mode */
-               property_enable(base, &rphy->phy_cfg->chg_det.opmode, false);
+               if (!vbus_attach)
+                       property_enable(base, &rphy->phy_cfg->chg_det.opmode, false);
                /* Start DCD processing stage 1 */
                rockchip_chg_enable_dcd(rphy, true);
                rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
@@ -894,7 +895,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
                fallthrough;
        case USB_CHG_STATE_DETECTED:
                /* put the controller in normal mode */
-               property_enable(base, &rphy->phy_cfg->chg_det.opmode, true);
+               if (!vbus_attach)
+                       property_enable(base, &rphy->phy_cfg->chg_det.opmode, true);
                rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
                dev_dbg(&rport->phy->dev, "charger = %s\n",
                         chg_to_string(rphy->chg_type));