From: Andreas Zdziarstek <andreas.zdziarstek@gmail.com>
To: Vinod Koul <vkoul@kernel.org>,
Neil Armstrong <neil.armstrong@linaro.org>
Cc: Heiko Stuebner <heiko@sntech.de>, Jonas Karlman <jonas@kwiboo.se>,
Frank Wang <frank.wang@rock-chips.com>,
Louis Chauvet <louis.chauvet@bootlin.com>,
Luca Ceresoli <luca.ceresoli@bootlin.com>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
devicetree@vger.kernel.org, linux-phy@lists.infradead.org,
linux-rockchip@lists.infradead.org,
linux-arm-kernel@lists.infradead.org, linux-usb@vger.kernel.org,
linux-kernel@vger.kernel.org,
Andreas Zdziarstek <andreas.zdziarstek@gmail.com>
Subject: [RFC PATCH v1 1/2] phy: rockchip: inno-usb2: keep peripheral-only OTG port active
Date: Tue, 7 Jul 2026 00:36:26 +0200 [thread overview]
Message-ID: <20260706223627.113814-2-andreas.zdziarstek@gmail.com> (raw)
In-Reply-To: <20260706223627.113814-1-andreas.zdziarstek@gmail.com>
The OTG state machine autonomously suspends the OTG port whenever it
decides no usable VBUS session is present. On the initial sample after
init, when a dedicated charger is detected, on peripheral disconnect
and on host-session end. It calls rockchip_usb2phy_power_off()
directly, underneath the USB controller.
For a dr_mode="peripheral" port this kills the USB gadget on any boot
without an attached cable. The state machine suspends the port shortly
after init, resulting in "failed to enable ep0out", ep0 start transfer
returns -EINVAL). The gadget remains unrecoverable in user space
afterwards.
Skip the state machine's autonomous power-offs when the port is
peripheral-only. VBUS detection, extcon signalling and charger
detection are unaffected, and controller-initiated power management
via phy_power_on()/phy_power_off() keeps working.
Signed-off-by: Andreas Zdziarstek <andreas.zdziarstek@gmail.com>
---
drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 27 +++++++++++++++----
1 file changed, 22 insertions(+), 5 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index 7d8a533f24ae..9b138b7aaeb8 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -670,6 +670,23 @@ static const struct phy_ops rockchip_usb2phy_ops = {
.owner = THIS_MODULE,
};
+/*
+ * Autonomous power-off from the OTG state machine or charger detection.
+ *
+ * A peripheral-only port shouldn't be power-gated behind the controller's
+ * back. If the gadget (re)binds while the PHY is suspended, the
+ * controller's ep0 setup fails and the gadget stays dead even when a VBUS
+ * session appears later. Keep the phy active on peripheral ports for
+ * correct connection detection.
+ */
+static void rockchip_usb2phy_sm_power_off(struct rockchip_usb2phy_port *rport)
+{
+ if (rport->mode == USB_DR_MODE_PERIPHERAL)
+ return;
+
+ rockchip_usb2phy_power_off(rport->phy);
+}
+
static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
{
struct rockchip_usb2phy_port *rport =
@@ -693,7 +710,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
case OTG_STATE_UNDEFINED:
rport->state = OTG_STATE_B_IDLE;
if (!vbus_attach)
- rockchip_usb2phy_power_off(rport->phy);
+ rockchip_usb2phy_sm_power_off(rport);
fallthrough;
case OTG_STATE_B_IDLE:
if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) > 0) {
@@ -719,7 +736,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
break;
case POWER_SUPPLY_TYPE_USB_DCP:
dev_dbg(&rport->phy->dev, "dcp cable is connected\n");
- rockchip_usb2phy_power_off(rport->phy);
+ rockchip_usb2phy_sm_power_off(rport);
notify_charger = true;
sch_work = true;
cable = EXTCON_CHG_USB_DCP;
@@ -765,7 +782,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
rport->state = OTG_STATE_B_IDLE;
delay = 0;
- rockchip_usb2phy_power_off(rport->phy);
+ rockchip_usb2phy_sm_power_off(rport);
}
sch_work = true;
break;
@@ -773,7 +790,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) == 0) {
dev_dbg(&rport->phy->dev, "usb otg host disconnect\n");
rport->state = OTG_STATE_B_IDLE;
- rockchip_usb2phy_power_off(rport->phy);
+ rockchip_usb2phy_sm_power_off(rport);
}
break;
default:
@@ -838,7 +855,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
switch (rphy->chg_state) {
case USB_CHG_STATE_UNDEFINED:
if (!rport->suspended && !vbus_attach)
- rockchip_usb2phy_power_off(rport->phy);
+ rockchip_usb2phy_sm_power_off(rport);
/* put the controller in non-driving mode */
if (!vbus_attach)
property_enable(rphy->grf, &rphy->phy_cfg->chg_det.opmode, false);
--
2.53.0
next prev parent reply other threads:[~2026-07-06 22:36 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-06 22:36 [RFC PATCH v1 0/2] phy: rockchip: inno-usb2: fix USB gadget hot-plug on peripheral-only OTG ports Andreas Zdziarstek
2026-07-06 22:36 ` Andreas Zdziarstek [this message]
2026-07-06 22:36 ` [RFC PATCH v1 2/2] arm64: dts: rockchip: fix gadget hot-plug on ODROID-M1S micro-USB Andreas Zdziarstek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260706223627.113814-2-andreas.zdziarstek@gmail.com \
--to=andreas.zdziarstek@gmail.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=frank.wang@rock-chips.com \
--cc=heiko@sntech.de \
--cc=jonas@kwiboo.se \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-phy@lists.infradead.org \
--cc=linux-rockchip@lists.infradead.org \
--cc=linux-usb@vger.kernel.org \
--cc=louis.chauvet@bootlin.com \
--cc=luca.ceresoli@bootlin.com \
--cc=neil.armstrong@linaro.org \
--cc=robh@kernel.org \
--cc=vkoul@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox