* [PATCH v7 01/27] dt-bindings: phy: rockchip-usbdp: add improved ports scheme
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 02/27] phy: rockchip: usbdp: Update mode_change after error handling Sebastian Reichel
` (25 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
Currently the Rockchip USBDP PHY is missing a documented port scheme.
Meanwhile upstream RK3588 DTS files are a bit messy and use different
port schemes. The upstream USBDP PHY Linux kernel driver does not yet
parse the ports at all and thus does not create any implicit ABI either.
But with the current mess it is not possible to properly support USB-C
DP AltMode. Thus this introduces a proper port scheme following roughly
the ports design of the Qualcomm QMP USB4-USB3-DP PHY controller binding
with a slight difference that there is an additional port for the
USB-C SBU port as the Rockchip USB-DP PHY also contains the SBU mux.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
.../bindings/phy/phy-rockchip-usbdp.yaml | 23 ++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml b/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
index 8b7059d5b182..f728acf057e4 100644
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
@@ -114,6 +114,29 @@ properties:
A port node to link the PHY to a TypeC controller for the purpose of
handling orientation switching.
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ Output endpoint of the PHY for USB (or DP when configured into 4 lane
+ mode), which should point to the superspeed port of a USB connector.
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Incoming endpoint from the USB controller
+
+ port@2:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Incoming endpoint from the DisplayPort controller
+
+ port@3:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ Output endpoint of the PHY for DP, which should either point to the
+ SBU port of a USB-C connector or a DisplayPort connector input port.
+
required:
- compatible
- reg
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 02/27] phy: rockchip: usbdp: Update mode_change after error handling
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 01/27] dt-bindings: phy: rockchip-usbdp: add improved ports scheme Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 18:00 ` sashiko-bot
2026-06-25 17:39 ` [PATCH v7 03/27] phy: rockchip: usbdp: Do not lose USB3 PHY status Sebastian Reichel
` (24 subsequent siblings)
26 siblings, 1 reply; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel, Sashiko
If rk_udphy_init() or rk_udphy_setup() fails, the reinit will not be
tried again. Fix this by only updating the variable after all potential
errors have been handled.
Note, that no errors have been seen on real hardware and failures would
most likely be fatal and require at least a full reboot as the function
already asserts the PHY reset lines. So this is more of a theoretical
issue.
Fixes: 2f70bbddeb45 ("phy: rockchip: add usbdp combo phy driver")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/linux-phy/20260612163835.8D5471F000E9@smtp.kernel.org/
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index fba35510d88c..a5ffdf7a6e76 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -1000,15 +1000,14 @@ static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode)
}
if (udphy->status == UDPHY_MODE_NONE) {
- udphy->mode_change = false;
ret = rk_udphy_setup(udphy);
if (ret)
return ret;
if (udphy->mode & UDPHY_MODE_USB)
rk_udphy_u3_port_disable(udphy, false);
- } else if (udphy->mode_change) {
udphy->mode_change = false;
+ } else if (udphy->mode_change) {
udphy->status = UDPHY_MODE_NONE;
if (udphy->mode == UDPHY_MODE_DP)
rk_udphy_u3_port_disable(udphy, true);
@@ -1017,6 +1016,7 @@ static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode)
ret = rk_udphy_setup(udphy);
if (ret)
return ret;
+ udphy->mode_change = false;
}
udphy->status |= mode;
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* Re: [PATCH v7 02/27] phy: rockchip: usbdp: Update mode_change after error handling
2026-06-25 17:39 ` [PATCH v7 02/27] phy: rockchip: usbdp: Update mode_change after error handling Sebastian Reichel
@ 2026-06-25 18:00 ` sashiko-bot
0 siblings, 0 replies; 37+ messages in thread
From: sashiko-bot @ 2026-06-25 18:00 UTC (permalink / raw)
To: Sebastian Reichel
Cc: devicetree, olteanv, neil.armstrong, linux-phy, conor+dt, vkoul,
robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Asynchronous mode changes orphan PHY status bits causing permanent clock and PHY power leaks.
--
commit 1706823bf92c7aae72801ef7a1f3c4258e09e79e
Author: Sebastian Reichel <sebastian.reichel@collabora.com>
phy: rockchip: usbdp: Update mode_change after error handling
This commit updates rk_udphy_power_on() to clear the mode_change flag
only after all potential errors have been handled. This ensures that
if initialization fails, the driver will correctly attempt to
reinitialize on the next try.
Closes: https://lore.kernel.org/linux-phy/20260612163835.8D5471F000E9@smtp.kernel.org/
> diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> index fba35510d88ce..a5ffdf7a6e76b 100644
> --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
> +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> @@ -1000,15 +1000,14 @@ static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode)
> }
>
> if (udphy->status == UDPHY_MODE_NONE) {
> - udphy->mode_change = false;
> ret = rk_udphy_setup(udphy);
> if (ret)
> return ret;
>
> if (udphy->mode & UDPHY_MODE_USB)
> rk_udphy_u3_port_disable(udphy, false);
[Severity: High]
This isn't a bug introduced by this patch, but could asynchronous mode
changes orphan PHY status bits here and cause permanent clock and power
leaks?
If a Type-C AltMode is negotiated that drops a previously available mode
(for example, dropping USB when transitioning to TYPEC_DP_STATE_C), the
Type-C mux callback in rk_udphy_typec_mux_set() updates the volatile
udphy->mode asynchronously:
rk_udphy_set_typec_state(udphy, state->mode);
When the USB framework reacts and calls phy_exit(), rk_udphy_usb3_phy_exit()
checks the newly updated mode instead of the active status:
if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs)
return 0;
rk_udphy_power_off(udphy, UDPHY_MODE_USB);
Because udphy->mode no longer contains the USB bit, the driver aborts early
without actually powering off the hardware.
Additionally, rk_udphy_power_off() itself redundantly checks udphy->mode:
if (!(udphy->mode & mode)) {
dev_info(udphy->dev, "mode 0x%02x is not support\n", mode);
return;
}
This leaves the active mode bit permanently orphaned in udphy->status,
which prevents rk_udphy_disable() from ever executing. Should the teardown
paths be validating against udphy->status instead of udphy->mode to avoid
this desynchronization?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260625-rockchip-usbdp-cleanup-v7-0-38eb3cf654fd@collabora.com?part=2
^ permalink raw reply [flat|nested] 37+ messages in thread
* [PATCH v7 03/27] phy: rockchip: usbdp: Do not lose USB3 PHY status
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 01/27] dt-bindings: phy: rockchip-usbdp: add improved ports scheme Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 02/27] phy: rockchip: usbdp: Update mode_change after error handling Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 18:06 ` sashiko-bot
2026-06-25 17:39 ` [PATCH v7 04/27] phy: rockchip: usbdp: Fix devm_clk_bulk_get_all check Sebastian Reichel
` (23 subsequent siblings)
26 siblings, 1 reply; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
By default (i.e. without manually enabling runtime PM) DWC3 requests the
USB3 PHY once and keeps it enabled all the time. When DisplayPort is
being requested later on, a mode change is needed. This re-initializes
the PHY. During re-initialization the status variable has incorrectly
been cleared, which means the tracking information for USB3 is lost.
This is not an immediate problem, since the DP side keeps the PHY
enabled. But once DP is toggled off, the whole PHY will be disabled.
This is a problem, because the USB side still needs it powered.
Fix things by not clearing the status flags.
Fixes: 2f70bbddeb45 ("phy: rockchip: add usbdp combo phy driver")
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index a5ffdf7a6e76..12dfdd470a78 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -1008,7 +1008,6 @@ static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode)
rk_udphy_u3_port_disable(udphy, false);
udphy->mode_change = false;
} else if (udphy->mode_change) {
- udphy->status = UDPHY_MODE_NONE;
if (udphy->mode == UDPHY_MODE_DP)
rk_udphy_u3_port_disable(udphy, true);
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* Re: [PATCH v7 03/27] phy: rockchip: usbdp: Do not lose USB3 PHY status
2026-06-25 17:39 ` [PATCH v7 03/27] phy: rockchip: usbdp: Do not lose USB3 PHY status Sebastian Reichel
@ 2026-06-25 18:06 ` sashiko-bot
0 siblings, 0 replies; 37+ messages in thread
From: sashiko-bot @ 2026-06-25 18:06 UTC (permalink / raw)
To: Sebastian Reichel
Cc: olteanv, robh, vkoul, neil.armstrong, linux-phy, conor+dt,
devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Preserving the PHY status across mode changes exposes a permanent power leak if the USB driver exits while a 4-lane DisplayPort is active.
--
commit eb97195758d636e8b97b5ffd69c0022de4826241
Author: Sebastian Reichel <sebastian.reichel@collabora.com>
phy: rockchip: usbdp: Do not lose USB3 PHY status
By default DWC3 requests the USB3 PHY once and keeps it enabled. When
DisplayPort is being requested later on, a mode change is needed which
re-initializes the PHY. This patch removes the clearing of the status variable
during re-initialization to ensure USB3 tracking information isn't lost.
> diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> index a5ffdf7a6e76b..12dfdd470a782 100644
> --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
> +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> @@ -1008,7 +1008,6 @@ static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode)
> rk_udphy_u3_port_disable(udphy, false);
> udphy->mode_change = false;
> } else if (udphy->mode_change) {
> - udphy->status = UDPHY_MODE_NONE;
[Severity: Medium]
Does this change introduce a potential power and clock leak when the USB
driver unbinds or suspends?
By preserving the UDPHY_MODE_USB bit in udphy->status across mode changes,
the status bit remains active while udphy->mode might be set to DP-only
(for example, when a 4-lane DisplayPort adapter is connected).
If rk_udphy_usb3_phy_exit() is called while the mode is DP-only, the early
mode check will trigger because udphy->mode lacks UDPHY_MODE_USB.
This causes an early return, skipping the call to rk_udphy_power_off()
and leaving the UDPHY_MODE_USB bit stranded in udphy->status.
Later, when DisplayPort is powered off and rk_udphy_power_off() clears the
UDPHY_MODE_DP bit, the status will drop to UDPHY_MODE_USB instead of
UDPHY_MODE_NONE. Could this bypass the final rk_udphy_disable() call,
leaving the PHY powered on and leaking the clock references indefinitely?
> if (udphy->mode == UDPHY_MODE_DP)
> rk_udphy_u3_port_disable(udphy, true);
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260625-rockchip-usbdp-cleanup-v7-0-38eb3cf654fd@collabora.com?part=3
^ permalink raw reply [flat|nested] 37+ messages in thread
* [PATCH v7 04/27] phy: rockchip: usbdp: Fix devm_clk_bulk_get_all check
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (2 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 03/27] phy: rockchip: usbdp: Do not lose USB3 PHY status Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 05/27] phy: rockchip: usbdp: Handle missing clock-names DT property gracefully Sebastian Reichel
` (22 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel, Sashiko
If devm_clk_bulk_get_all() returns -EPROBE_DEFER, it is replaced with
-ENODEV, permanently failing the driver probe instead of allowing it to
defer. Avoid masking the error code to fix the issue.
This effectively drops returning -ENODEV in case no clocks are being
described in DT. This special case will now be handled by the follow-up
check searching for "refclk" and exit with -EINVAL.
None of this will be hit in practice, since the driver is only used by
RK3588 and RK3576 - on these platforms the DT is validated to contain
the clocks and the clock driver is force probed early. Thus there is
no need to backport this.
Fixes: 2f70bbddeb45 ("phy: rockchip: add usbdp combo phy driver")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/linux-phy/20260612164107.C7DB21F000E9@smtp.kernel.org/
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 12dfdd470a78..2845a012eafc 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -427,8 +427,8 @@ static int rk_udphy_clk_init(struct rk_udphy *udphy, struct device *dev)
int i;
udphy->num_clks = devm_clk_bulk_get_all(dev, &udphy->clks);
- if (udphy->num_clks < 1)
- return -ENODEV;
+ if (udphy->num_clks < 0)
+ return udphy->num_clks;
/* used for configure phy reference clock frequency */
for (i = 0; i < udphy->num_clks; i++) {
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 05/27] phy: rockchip: usbdp: Handle missing clock-names DT property gracefully
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (3 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 04/27] phy: rockchip: usbdp: Fix devm_clk_bulk_get_all check Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:59 ` sashiko-bot
2026-06-25 17:39 ` [PATCH v7 06/27] phy: rockchip: usbdp: Drop seamless DP takeover Sebastian Reichel
` (21 subsequent siblings)
26 siblings, 1 reply; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel, Sashiko
The rk_udphy_clk_init() function would currently try to do a strncmp for
a NULL pointer, if DT specifies 'clocks' property, but no 'clock-names'
property. Fix this by making sure the clock has an id string set.
Note that DT binding requires setting clock-names, so this is only a
problem when booting a non-compliant device tree.
Fixes: 2f70bbddeb45 ("phy: rockchip: add usbdp combo phy driver")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/message/20260619154349.071321F000E9%40smtp.kernel.org
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 2845a012eafc..3fc8222fcaec 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -432,6 +432,9 @@ static int rk_udphy_clk_init(struct rk_udphy *udphy, struct device *dev)
/* used for configure phy reference clock frequency */
for (i = 0; i < udphy->num_clks; i++) {
+ if (!udphy->clks[i].id)
+ continue;
+
if (!strncmp(udphy->clks[i].id, "refclk", 6)) {
udphy->refclk = udphy->clks[i].clk;
break;
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* Re: [PATCH v7 05/27] phy: rockchip: usbdp: Handle missing clock-names DT property gracefully
2026-06-25 17:39 ` [PATCH v7 05/27] phy: rockchip: usbdp: Handle missing clock-names DT property gracefully Sebastian Reichel
@ 2026-06-25 17:59 ` sashiko-bot
0 siblings, 0 replies; 37+ messages in thread
From: sashiko-bot @ 2026-06-25 17:59 UTC (permalink / raw)
To: Sebastian Reichel
Cc: robh, vkoul, neil.armstrong, olteanv, devicetree, linux-phy,
conor+dt
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Unchecked NULL pointer dereference when comparing clock IDs from non-compliant Device Trees.
--
commit be75e70030d6a112304beae15bcbe8b9d870c214
Author: Sebastian Reichel <sebastian.reichel@collabora.com>
phy: rockchip: usbdp: Handle missing clock-names DT property gracefully
This patch adds a check to ensure the clock id string is present before
comparing it, preventing a null pointer dereference when parsing a
non-compliant device tree.
> diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> index 2845a012eafcc..3fc8222fcaec2 100644
> --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
> +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> @@ -432,6 +432,9 @@ static int rk_udphy_clk_init(struct rk_udphy *udphy, struct device *dev)
>
> /* used for configure phy reference clock frequency */
> for (i = 0; i < udphy->num_clks; i++) {
> + if (!udphy->clks[i].id)
> + continue;
> +
[Severity: High]
This isn't a bug introduced by this patch, but since you are fixing the
missing clock-names behavior here, could this same vulnerability be
present in other drivers?
Looking at the tree, several other drivers also iterate over clocks
returned by devm_clk_bulk_get_all() and pass the id field directly to
strcmp() or strncmp() without checking if it is null.
For example, in drivers/phy/rockchip/phy-rockchip-inno-usb2.c:
rockchip_usb2phy_clk480m_register() does:
if (!strncmp(rphy->clks[i].id, "phyclk", 6)) {
Similarly, in drivers/phy/rockchip/phy-rockchip-naneng-combphy.c:
rockchip_combphy_parse_dt() does:
if (!strncmp(priv->clks[i].id, "ref", 3)) {
There appear to be similar unchecked usages in:
drivers/pci/controller/dwc/pci-imx6.c:imx_pcie_setup_phy()
drivers/spi/spi-rzv2h-rspi.c:rzv2h_rspi_probe()
drivers/crypto/rockchip/rk3288_crypto.c:rk_crypto_get_clks()
drivers/media/platform/nxp/imx8mq-mipi-csi2.c:imx8mq_mipi_csi_find_esc_clk()
Should these be audited and patched similarly to prevent a panic when
handling malformed device trees?
> if (!strncmp(udphy->clks[i].id, "refclk", 6)) {
> udphy->refclk = udphy->clks[i].clk;
> break;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260625-rockchip-usbdp-cleanup-v7-0-38eb3cf654fd@collabora.com?part=5
^ permalink raw reply [flat|nested] 37+ messages in thread
* [PATCH v7 06/27] phy: rockchip: usbdp: Drop seamless DP takeover
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (4 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 05/27] phy: rockchip: usbdp: Handle missing clock-names DT property gracefully Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:58 ` sashiko-bot
2026-06-25 17:39 ` [PATCH v7 07/27] phy: rockchip: usbdp: Handle rk_udphy_reset_deassert_all errors in init check Sebastian Reichel
` (20 subsequent siblings)
26 siblings, 1 reply; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel, Sashiko
If the bootloader already enabled DP, keeping it enabled here means
the DRM stack can do a seamless takeover. Right now the DRM does not
support this and the code will leak clock resources on module removal,
so just drop this feature.
Fixes: 2f70bbddeb45 ("phy: rockchip: add usbdp combo phy driver")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/linux-phy/20260612164107.C7DB21F000E9@smtp.kernel.org/
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 3fc8222fcaec..7fa3cd519577 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -939,9 +939,9 @@ static int rk_udphy_get_initial_status(struct rk_udphy *udphy)
regmap_read(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, &value);
if (FIELD_GET(CMN_DP_LANE_MUX_ALL, value) && FIELD_GET(CMN_DP_LANE_EN_ALL, value))
- udphy->status = UDPHY_MODE_DP;
- else
- rk_udphy_disable(udphy);
+ dev_dbg(udphy->dev, "Started with DP PHY pre-enabled; seamless takeover unsupported\n");
+
+ rk_udphy_disable(udphy);
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* Re: [PATCH v7 06/27] phy: rockchip: usbdp: Drop seamless DP takeover
2026-06-25 17:39 ` [PATCH v7 06/27] phy: rockchip: usbdp: Drop seamless DP takeover Sebastian Reichel
@ 2026-06-25 17:58 ` sashiko-bot
0 siblings, 0 replies; 37+ messages in thread
From: sashiko-bot @ 2026-06-25 17:58 UTC (permalink / raw)
To: Sebastian Reichel
Cc: conor+dt, robh, vkoul, linux-phy, neil.armstrong, olteanv,
devicetree
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Unconditionally disabling the DP PHY during probe can cause a fatal bus stall if the bootloader left the display pipeline active.
--
commit c915d0565d2bfe6851ea25d0f7d099f70a22703f
Author: Sebastian Reichel <sebastian.reichel@collabora.com>
phy: rockchip: usbdp: Drop seamless DP takeover
This commit removes seamless DP takeover support by unconditionally disabling
the DP PHY during initial status checks. It aims to prevent clock resource
leaks on module removal since the DRM stack does not yet support seamless
takeover.
Closes: https://lore.kernel.org/linux-phy/20260612164107.C7DB21F000E9@smtp.kernel.org/
> diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
> +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> @@ -939,9 +939,9 @@ static int rk_udphy_get_initial_status(struct rk_udphy *udphy)
>
> regmap_read(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, &value);
> if (FIELD_GET(CMN_DP_LANE_MUX_ALL, value) && FIELD_GET(CMN_DP_LANE_EN_ALL, value))
> - udphy->status = UDPHY_MODE_DP;
> - else
> - rk_udphy_disable(udphy);
> + dev_dbg(udphy->dev, "Started with DP PHY pre-enabled; seamless takeover unsupported\n");
> +
> + rk_udphy_disable(udphy);
[Severity: High]
Will this unconditional call to rk_udphy_disable() cause a fatal bus stall
if the bootloader left the display pipeline active?
If the bootloader leaves the DP PHY enabled and streaming for a splash
screen, the Video Output Processor (VOP) is actively pushing pixels to the
PHY and depending on its clocks.
By shutting down the PHY, cutting its clocks, and asserting resets here
before the VOP is stopped, the VOP could stall the AXI bus when its
downstream sink abruptly stops. This can lead to an asynchronous external
abort (SError) or a complete system hang.
Even without seamless DRM takeover support, should the PHY remain enabled
until the DRM driver gracefully tears down the display pipeline in the
correct hardware-mandated order (VOP first, then PHY)?
>
> return 0;
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260625-rockchip-usbdp-cleanup-v7-0-38eb3cf654fd@collabora.com?part=6
^ permalink raw reply [flat|nested] 37+ messages in thread
* [PATCH v7 07/27] phy: rockchip: usbdp: Handle rk_udphy_reset_deassert_all errors in init check
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (5 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 06/27] phy: rockchip: usbdp: Drop seamless DP takeover Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 08/27] phy: rockchip: usbdp: Limit DP lane count to muxed lanes Sebastian Reichel
` (19 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel, Sashiko
Fix theoretical issue, that failure to deassert the reset lines would
result in an SError in follow-up register access. Note, that this cannot
happen with current code, since the Rockchip reset driver never returns
any errors for (de)asserting reset lines.
Fixes: 2f70bbddeb45 ("phy: rockchip: add usbdp combo phy driver")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/message/20260619154903.2225A1F000E9%40smtp.kernel.org
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 7fa3cd519577..121dd78d8c16 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -935,15 +935,18 @@ static int rk_udphy_get_initial_status(struct rk_udphy *udphy)
return ret;
}
- rk_udphy_reset_deassert_all(udphy);
+ ret = rk_udphy_reset_deassert_all(udphy);
+ if (ret)
+ goto exit;
regmap_read(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, &value);
if (FIELD_GET(CMN_DP_LANE_MUX_ALL, value) && FIELD_GET(CMN_DP_LANE_EN_ALL, value))
dev_dbg(udphy->dev, "Started with DP PHY pre-enabled; seamless takeover unsupported\n");
+exit:
rk_udphy_disable(udphy);
- return 0;
+ return ret;
}
static int rk_udphy_parse_dt(struct rk_udphy *udphy)
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 08/27] phy: rockchip: usbdp: Limit DP lane count to muxed lanes
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (6 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 07/27] phy: rockchip: usbdp: Handle rk_udphy_reset_deassert_all errors in init check Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 18:07 ` sashiko-bot
2026-06-25 17:39 ` [PATCH v7 09/27] phy: rockchip: usbdp: Keep clocks running on PHY re-init Sebastian Reichel
` (18 subsequent siblings)
26 siblings, 1 reply; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel, Sashiko
In theory the DP controller could request 4 lanes when the PHY is
restricted to 2 lanes as the other half is used by USB3.
With the current user (DW-DP) this cannot happen, but as the check is
cheap and users might change in the future protect things accordingly.
Not doing so would corrupt USB3 usage by the following code configuring
the voltages.
Fixes: 2f70bbddeb45 ("phy: rockchip: add usbdp combo phy driver")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/linux-phy/20260612165546.98E1F1F000E9@smtp.kernel.org/
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 121dd78d8c16..2324f9050f63 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -1132,6 +1132,9 @@ static int rk_udphy_dp_phy_verify_link_rate(struct rk_udphy *udphy,
static int rk_udphy_dp_phy_verify_lanes(struct rk_udphy *udphy,
struct phy_configure_opts_dp *dp)
{
+ if (dp->lanes > udphy->dp_lanes)
+ return -EINVAL;
+
switch (dp->lanes) {
case 1:
case 2:
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* Re: [PATCH v7 08/27] phy: rockchip: usbdp: Limit DP lane count to muxed lanes
2026-06-25 17:39 ` [PATCH v7 08/27] phy: rockchip: usbdp: Limit DP lane count to muxed lanes Sebastian Reichel
@ 2026-06-25 18:07 ` sashiko-bot
0 siblings, 0 replies; 37+ messages in thread
From: sashiko-bot @ 2026-06-25 18:07 UTC (permalink / raw)
To: Sebastian Reichel
Cc: linux-phy, robh, conor+dt, neil.armstrong, olteanv, devicetree,
vkoul
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The target patch introduces a validation check against `udphy->dp_lanes`, but this struct member does not exist at this point in the patch series, causing a fatal build error. Even if it did exist, it is not initialized, leading to permanent validation failure.
--
commit 4d319652ccfe3b1db53193c06a94733191acf3bc
Author: Sebastian Reichel <sebastian.reichel@collabora.com>
phy: rockchip: usbdp: Limit DP lane count to muxed lanes
This commit adds a check to limit the DP lane count to the number of muxed
lanes available on the PHY, preventing the DP controller from requesting
4 lanes when restricted to 2.
Closes: https://lore.kernel.org/linux-phy/20260612165546.98E1F1F000E9@smtp.kernel.org/
> diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> index 121dd78d8c161..2324f9050f638 100644
> --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
> +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> @@ -1132,6 +1132,9 @@ static int rk_udphy_dp_phy_verify_link_rate(struct rk_udphy *udphy,
> static int rk_udphy_dp_phy_verify_lanes(struct rk_udphy *udphy,
> struct phy_configure_opts_dp *dp)
> {
> + if (dp->lanes > udphy->dp_lanes)
> + return -EINVAL;
> +
[Severity: High]
Does this break the build at this point in the patch series?
It appears that the dp_lanes member of struct rk_udphy is not yet declared
or initialized at this point in the tree. This would cause a compilation
failure and break git bisect. Additionally, if the field were present but
uninitialized, it would evaluate to 0 and cause this check to unconditionally
return -EINVAL, breaking DisplayPort configuration.
I understand this is resolved later in the patch series by commit
02003c09070591a7 ("phy: rockchip: usbdp: Support single-lane DP"), which
adds and correctly initializes the dp_lanes struct member. Could the struct
member addition be moved to this commit to ensure the build remains fully
bisectable?
> switch (dp->lanes) {
> case 1:
> case 2:
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260625-rockchip-usbdp-cleanup-v7-0-38eb3cf654fd@collabora.com?part=8
^ permalink raw reply [flat|nested] 37+ messages in thread
* [PATCH v7 09/27] phy: rockchip: usbdp: Keep clocks running on PHY re-init
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (7 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 08/27] phy: rockchip: usbdp: Limit DP lane count to muxed lanes Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 10/27] phy: rockchip: usbdp: Amend SSC modulation deviation Sebastian Reichel
` (17 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
When a mode change is required rk_udphy_power_on() disables
the clocks and then calls rk_udphy_setup(), which then enables
all the clocks again before continuing with rk_udphy_init().
Considering that rk_udphy_init() does assert the reset lines,
re-enabling the clocks is just delaying things. Avoid it by
directly calling rk_udphy_init().
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 2324f9050f63..989a7884d8b5 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -1017,8 +1017,7 @@ static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode)
if (udphy->mode == UDPHY_MODE_DP)
rk_udphy_u3_port_disable(udphy, true);
- rk_udphy_disable(udphy);
- ret = rk_udphy_setup(udphy);
+ ret = rk_udphy_init(udphy);
if (ret)
return ret;
udphy->mode_change = false;
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 10/27] phy: rockchip: usbdp: Amend SSC modulation deviation
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (8 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 09/27] phy: rockchip: usbdp: Keep clocks running on PHY re-init Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 11/27] phy: rockchip: usbdp: Fix LFPS detect threshold control Sebastian Reichel
` (16 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
From: Frank Wang <frank.wang@rock-chips.com>
Move SSC modulation deviation into private config of clock
- 24M: 0x00d4[5:0] = 0x30
- 26M: 0x00d4[5:0] = 0x33
Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
[Taken over from rockchip's kernel tree; register 0x00d4 is not
described in the TRM]
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 989a7884d8b5..93df673e181b 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -350,7 +350,8 @@ static const struct reg_sequence rk_udphy_24m_refclk_cfg[] = {
{0x0a64, 0xa8}, {0x1a3c, 0xd0},
{0x1a44, 0xd0}, {0x1a48, 0x01},
{0x1a4c, 0x0d}, {0x1a54, 0xe0},
- {0x1a5c, 0xe0}, {0x1a64, 0xa8}
+ {0x1a5c, 0xe0}, {0x1a64, 0xa8},
+ {0x00d4, 0x30}
};
static const struct reg_sequence rk_udphy_26m_refclk_cfg[] = {
@@ -377,7 +378,7 @@ static const struct reg_sequence rk_udphy_26m_refclk_cfg[] = {
{0x0c30, 0x0e}, {0x0c48, 0x06},
{0x1c30, 0x0e}, {0x1c48, 0x06},
{0x028c, 0x18}, {0x0af0, 0x00},
- {0x1af0, 0x00}
+ {0x1af0, 0x00}, {0x00d4, 0x33}
};
static const struct reg_sequence rk_udphy_init_sequence[] = {
@@ -412,8 +413,7 @@ static const struct reg_sequence rk_udphy_init_sequence[] = {
{0x0070, 0x7d}, {0x0074, 0x68},
{0x0af4, 0x1a}, {0x1af4, 0x1a},
{0x0440, 0x3f}, {0x10d4, 0x08},
- {0x20d4, 0x08}, {0x00d4, 0x30},
- {0x0024, 0x6e},
+ {0x20d4, 0x08}, {0x0024, 0x6e}
};
static inline int rk_udphy_grfreg_write(struct regmap *base,
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 11/27] phy: rockchip: usbdp: Fix LFPS detect threshold control
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (9 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 10/27] phy: rockchip: usbdp: Amend SSC modulation deviation Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 12/27] phy: rockchip: usbdp: Add missing mode_change update Sebastian Reichel
` (15 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel, William Wu
From: William Wu <william.wu@rock-chips.com>
According to the LFPS Tx Low Power/LFPS Rx Detect Threshold [1],
the device under test(DUT) must not respond if LFPS below the
minimum LFPS Rx Detect Threshold 100mV. Test fail on Rockchip
platforms, because the default LFPS detect threshold is set to
65mV.
The USBDP PHY LFPS detect threshold voltage could be set to
30mV ~ 140mV, and since there could be 10-20% PVT variation,
we set LFPS detect threshold voltage to 110mV.
[1] https://compliance.usb.org/resources/LFPS_Rx_Tx_Low_Power_Compliance_Update_Rev5.pdf
Signed-off-by: William Wu <william.wu@rock-chips.com>
[Taken over from rockchip's kernel tree; the registers are not described
in the TRM]
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 93df673e181b..1067ddf2d742 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -413,7 +413,8 @@ static const struct reg_sequence rk_udphy_init_sequence[] = {
{0x0070, 0x7d}, {0x0074, 0x68},
{0x0af4, 0x1a}, {0x1af4, 0x1a},
{0x0440, 0x3f}, {0x10d4, 0x08},
- {0x20d4, 0x08}, {0x0024, 0x6e}
+ {0x20d4, 0x08}, {0x0024, 0x6e},
+ {0x09c0, 0x0a}, {0x19c0, 0x0a}
};
static inline int rk_udphy_grfreg_write(struct regmap *base,
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 12/27] phy: rockchip: usbdp: Add missing mode_change update
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (10 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 11/27] phy: rockchip: usbdp: Fix LFPS detect threshold control Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 18:02 ` sashiko-bot
2026-06-25 17:39 ` [PATCH v7 13/27] phy: rockchip: usbdp: Support single-lane DP Sebastian Reichel
` (14 subsequent siblings)
26 siblings, 1 reply; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
rk_udphy_set_typec_default_mapping() updates the available modes,
but does not set the mode_change as required. This results in
missing re-initialization and thus non-working DisplayPort.
Fix this issue by introducing a new helper to update the available
modes.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 1067ddf2d742..f079715f7da2 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -622,6 +622,15 @@ static void rk_udphy_dp_hpd_event_trigger(struct rk_udphy *udphy, bool hpd)
rk_udphy_grfreg_write(udphy->vogrf, &cfg->vogrfcfg[udphy->id].hpd_trigger, hpd);
}
+static void rk_udphy_mode_set(struct rk_udphy *udphy, u8 mode)
+{
+ if (udphy->mode == mode)
+ return;
+
+ udphy->mode_change = true;
+ udphy->mode = mode;
+}
+
static void rk_udphy_set_typec_default_mapping(struct rk_udphy *udphy)
{
if (udphy->flip) {
@@ -652,7 +661,7 @@ static void rk_udphy_set_typec_default_mapping(struct rk_udphy *udphy)
gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 1);
}
- udphy->mode = UDPHY_MODE_DP_USB;
+ rk_udphy_mode_set(udphy, UDPHY_MODE_DP_USB);
}
static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw,
@@ -1394,10 +1403,7 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
usleep_range(750, 800);
rk_udphy_dp_hpd_event_trigger(udphy, true);
} else if (data->status & DP_STATUS_HPD_STATE) {
- if (udphy->mode != mode) {
- udphy->mode = mode;
- udphy->mode_change = true;
- }
+ rk_udphy_mode_set(udphy, mode);
rk_udphy_dp_hpd_event_trigger(udphy, true);
} else {
rk_udphy_dp_hpd_event_trigger(udphy, false);
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* Re: [PATCH v7 12/27] phy: rockchip: usbdp: Add missing mode_change update
2026-06-25 17:39 ` [PATCH v7 12/27] phy: rockchip: usbdp: Add missing mode_change update Sebastian Reichel
@ 2026-06-25 18:02 ` sashiko-bot
0 siblings, 0 replies; 37+ messages in thread
From: sashiko-bot @ 2026-06-25 18:02 UTC (permalink / raw)
To: Sebastian Reichel
Cc: olteanv, conor+dt, devicetree, robh, vkoul, neil.armstrong,
linux-phy
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] When dynamically exiting DisplayPort Alternate Mode, the PHY mode is not updated to reflect the new state, which can silently prevent USB SuperSpeed from powering on. A subsequent patch in the series attempts to fix this but fails due to a logical bug.
--
commit a13f2ad68259618e56bf0f7f6e7be4e8d3391f8e
Author: Sebastian Reichel <sebastian.reichel@collabora.com>
phy: rockchip: usbdp: Add missing mode_change update
This commit introduces a new helper rk_udphy_mode_set() to update the
available modes. It ensures the mode_change flag is set when required
so that DisplayPort properly re-initializes.
> diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> index 1067ddf2d7422..f079715f7da21 100644
> --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
> +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
[ ... ]
> @@ -1394,10 +1403,7 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
> usleep_range(750, 800);
> rk_udphy_dp_hpd_event_trigger(udphy, true);
> } else if (data->status & DP_STATUS_HPD_STATE) {
> - if (udphy->mode != mode) {
> - udphy->mode = mode;
> - udphy->mode_change = true;
> - }
> + rk_udphy_mode_set(udphy, mode);
[Severity: High]
This isn't a bug introduced by this patch, but there is a pre-existing issue
in rk_udphy_typec_mux_set() regarding how state transitions are handled.
When dynamically exiting DisplayPort Alternate Mode, does the driver
silently prevent USB SuperSpeed from powering on?
If a user unplugs a DP accessory, the Type-C subsystem sends a mux state
update with state->mode set to TYPEC_STATE_SAFE or TYPEC_STATE_USB, and
state->alt set to NULL.
The code evaluates this condition:
if (state->mode >= TYPEC_STATE_MODAL || !state->alt ||
state->alt->svid != USB_TYPEC_DP_SID)
return 0;
For TYPEC_STATE_SAFE and TYPEC_STATE_USB, state->alt is NULL. This makes
!state->alt evaluate to true. Because of the || operator, the entire
statement evaluates to true, causing the function to return 0 and
ignore the event entirely instead of repowering the PHY correctly.
A later patch in the series ("phy: rockchip: usbdp: Properly handle
TYPEC_STATE_SAFE and TYPEC_STATE_USB") attempts to fix this, but the logic
in that patch still contains this error because it fails to restrict the
state->alt checks to only the modal states.
Could the condition be grouped to properly handle the non-modal states?
> rk_udphy_dp_hpd_event_trigger(udphy, true);
> } else {
> rk_udphy_dp_hpd_event_trigger(udphy, false);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260625-rockchip-usbdp-cleanup-v7-0-38eb3cf654fd@collabora.com?part=12
^ permalink raw reply [flat|nested] 37+ messages in thread
* [PATCH v7 13/27] phy: rockchip: usbdp: Support single-lane DP
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (11 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 12/27] phy: rockchip: usbdp: Add missing mode_change update Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 14/27] phy: rockchip: usbdp: Rename DP lane functions Sebastian Reichel
` (13 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
From: Zhang Yubing <yubing.zhang@rock-chips.com>
Implement support for using just a single DisplayPort line.
Signed-off-by: Zhang Yubing <yubing.zhang@rock-chips.com>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 64 +++++++++++++------------------
1 file changed, 27 insertions(+), 37 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index f079715f7da2..e9e3f36f9e09 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -193,6 +193,7 @@ struct rk_udphy {
int id;
bool dp_in_use;
+ int dp_lanes;
/* PHY const config */
const struct rk_udphy_cfg *cfgs;
@@ -540,6 +541,13 @@ static void rk_udphy_usb_bvalid_enable(struct rk_udphy *udphy, u8 enable)
* <0 1> dpln0 dpln1 usbrx usbtx
* <2 3> usbrx usbtx dpln0 dpln1
* ---------------------------------------------------------------------------
+ * if 1 lane for dp function, 2 lane for usb function, define rockchip,dp-lane-mux = <x>;
+ * sample as follow:
+ * ---------------------------------------------------------------------------
+ * B11-B10 A2-A3 A11-A10 B2-B3
+ * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx)
+ * <0> dpln0 \ usbrx usbtx
+ * ---------------------------------------------------------------------------
*/
static void rk_udphy_dplane_select(struct rk_udphy *udphy)
@@ -547,18 +555,18 @@ static void rk_udphy_dplane_select(struct rk_udphy *udphy)
const struct rk_udphy_cfg *cfg = udphy->cfgs;
u32 value = 0;
- switch (udphy->mode) {
- case UDPHY_MODE_DP:
- value |= 2 << udphy->dp_lane_sel[2] * 2;
+ switch (udphy->dp_lanes) {
+ case 4:
value |= 3 << udphy->dp_lane_sel[3] * 2;
+ value |= 2 << udphy->dp_lane_sel[2] * 2;
fallthrough;
- case UDPHY_MODE_DP_USB:
- value |= 0 << udphy->dp_lane_sel[0] * 2;
+ case 2:
value |= 1 << udphy->dp_lane_sel[1] * 2;
- break;
+ fallthrough;
- case UDPHY_MODE_USB:
+ case 1:
+ value |= 0 << udphy->dp_lane_sel[0] * 2;
break;
default:
@@ -571,28 +579,6 @@ static void rk_udphy_dplane_select(struct rk_udphy *udphy)
FIELD_PREP(DP_AUX_DOUT_SEL, udphy->dp_aux_dout_sel) | value);
}
-static int rk_udphy_dplane_get(struct rk_udphy *udphy)
-{
- int dp_lanes;
-
- switch (udphy->mode) {
- case UDPHY_MODE_DP:
- dp_lanes = 4;
- break;
-
- case UDPHY_MODE_DP_USB:
- dp_lanes = 2;
- break;
-
- case UDPHY_MODE_USB:
- default:
- dp_lanes = 0;
- break;
- }
-
- return dp_lanes;
-}
-
static void rk_udphy_dplane_enable(struct rk_udphy *udphy, int dp_lanes)
{
u32 val = 0;
@@ -662,6 +648,7 @@ static void rk_udphy_set_typec_default_mapping(struct rk_udphy *udphy)
}
rk_udphy_mode_set(udphy, UDPHY_MODE_DP_USB);
+ udphy->dp_lanes = 2;
}
static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw,
@@ -900,7 +887,7 @@ static int rk_udphy_parse_lane_mux_data(struct rk_udphy *udphy)
return 0;
}
- if (num_lanes != 2 && num_lanes != 4)
+ if (num_lanes != 1 && num_lanes != 2 && num_lanes != 4)
return dev_err_probe(udphy->dev, -EINVAL,
"invalid number of lane mux\n");
@@ -926,9 +913,11 @@ static int rk_udphy_parse_lane_mux_data(struct rk_udphy *udphy)
}
udphy->mode = UDPHY_MODE_DP;
- if (num_lanes == 2) {
+ udphy->dp_lanes = num_lanes;
+ if (num_lanes == 1 || num_lanes == 2) {
udphy->mode |= UDPHY_MODE_USB;
- udphy->flip = (udphy->lane_mux_sel[0] == PHY_LANE_MUX_DP);
+ udphy->flip = (udphy->lane_mux_sel[0] == PHY_LANE_MUX_DP) ||
+ (udphy->lane_mux_sel[1] == PHY_LANE_MUX_DP);
}
return 0;
@@ -1080,18 +1069,17 @@ static int rk_udphy_dp_phy_exit(struct phy *phy)
static int rk_udphy_dp_phy_power_on(struct phy *phy)
{
struct rk_udphy *udphy = phy_get_drvdata(phy);
- int ret, dp_lanes;
+ int ret;
mutex_lock(&udphy->mutex);
- dp_lanes = rk_udphy_dplane_get(udphy);
- phy_set_bus_width(phy, dp_lanes);
+ phy_set_bus_width(phy, udphy->dp_lanes);
ret = rk_udphy_power_on(udphy, UDPHY_MODE_DP);
if (ret)
goto unlock;
- rk_udphy_dplane_enable(udphy, dp_lanes);
+ rk_udphy_dplane_enable(udphy, udphy->dp_lanes);
rk_udphy_dplane_select(udphy);
@@ -1374,6 +1362,7 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP;
udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP;
mode = UDPHY_MODE_DP;
+ udphy->dp_lanes = 4;
break;
case TYPEC_DP_STATE_D:
@@ -1390,6 +1379,7 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP;
}
mode = UDPHY_MODE_DP_USB;
+ udphy->dp_lanes = 2;
break;
}
@@ -1538,7 +1528,7 @@ static int rk_udphy_probe(struct platform_device *pdev)
ret = PTR_ERR(udphy->phy_dp);
return dev_err_probe(dev, ret, "failed to create DP phy\n");
}
- phy_set_bus_width(udphy->phy_dp, rk_udphy_dplane_get(udphy));
+ phy_set_bus_width(udphy->phy_dp, udphy->dp_lanes);
udphy->phy_dp->attrs.max_link_rate = 8100;
phy_set_drvdata(udphy->phy_dp, udphy);
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 14/27] phy: rockchip: usbdp: Rename DP lane functions
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (12 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 13/27] phy: rockchip: usbdp: Support single-lane DP Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 15/27] phy: rockchip: usbdp: Use FIELD_PREP_WM16_CONST Sebastian Reichel
` (12 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
The common prefix for DisplayPort related functions is rk_udphy_dp_
(with a final _), so update the two DP lane functions to follow that
scheme.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index e9e3f36f9e09..6ec9ab9d1e64 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -550,7 +550,7 @@ static void rk_udphy_usb_bvalid_enable(struct rk_udphy *udphy, u8 enable)
* ---------------------------------------------------------------------------
*/
-static void rk_udphy_dplane_select(struct rk_udphy *udphy)
+static void rk_udphy_dp_lane_select(struct rk_udphy *udphy)
{
const struct rk_udphy_cfg *cfg = udphy->cfgs;
u32 value = 0;
@@ -579,7 +579,7 @@ static void rk_udphy_dplane_select(struct rk_udphy *udphy)
FIELD_PREP(DP_AUX_DOUT_SEL, udphy->dp_aux_dout_sel) | value);
}
-static void rk_udphy_dplane_enable(struct rk_udphy *udphy, int dp_lanes)
+static void rk_udphy_dp_lane_enable(struct rk_udphy *udphy, int dp_lanes)
{
u32 val = 0;
int i;
@@ -1079,9 +1079,9 @@ static int rk_udphy_dp_phy_power_on(struct phy *phy)
if (ret)
goto unlock;
- rk_udphy_dplane_enable(udphy, udphy->dp_lanes);
+ rk_udphy_dp_lane_enable(udphy, udphy->dp_lanes);
- rk_udphy_dplane_select(udphy);
+ rk_udphy_dp_lane_select(udphy);
unlock:
mutex_unlock(&udphy->mutex);
@@ -1099,7 +1099,7 @@ static int rk_udphy_dp_phy_power_off(struct phy *phy)
struct rk_udphy *udphy = phy_get_drvdata(phy);
mutex_lock(&udphy->mutex);
- rk_udphy_dplane_enable(udphy, 0);
+ rk_udphy_dp_lane_enable(udphy, 0);
rk_udphy_power_off(udphy, UDPHY_MODE_DP);
mutex_unlock(&udphy->mutex);
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 15/27] phy: rockchip: usbdp: Use FIELD_PREP_WM16_CONST
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (13 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 14/27] phy: rockchip: usbdp: Rename DP lane functions Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 16/27] phy: rockchip: usbdp: Cleanup DP lane selection function Sebastian Reichel
` (11 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
Cleanup code by replacing open-coded version of FIELD_PREP_WM16_CONST
with the existing helper macro.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 6ec9ab9d1e64..1bae8172d1fe 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -12,6 +12,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
+#include <linux/hw_bitfield.h>
#include <linux/mfd/syscon.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
@@ -75,7 +76,6 @@
#define TRSV_LN2_MON_RX_CDR_DONE_OFFSET 0x1b84 /* trsv_reg06E1 */
#define TRSV_LN2_MON_RX_CDR_LOCK_DONE BIT(0)
-#define BIT_WRITEABLE_SHIFT 16
#define PHY_AUX_DP_DATA_POL_NORMAL 0
#define PHY_AUX_DP_DATA_POL_INVERT 1
#define PHY_LANE_MUX_USB 0
@@ -104,8 +104,8 @@ struct rk_udphy_grf_reg {
#define _RK_UDPHY_GEN_GRF_REG(offset, mask, disable, enable) \
{\
offset, \
- FIELD_PREP_CONST(mask, disable) | (mask << BIT_WRITEABLE_SHIFT), \
- FIELD_PREP_CONST(mask, enable) | (mask << BIT_WRITEABLE_SHIFT), \
+ FIELD_PREP_WM16_CONST(mask, disable), \
+ FIELD_PREP_WM16_CONST(mask, enable), \
}
#define RK_UDPHY_GEN_GRF_REG(offset, bitend, bitstart, disable, enable) \
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 16/27] phy: rockchip: usbdp: Cleanup DP lane selection function
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (14 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 15/27] phy: rockchip: usbdp: Use FIELD_PREP_WM16_CONST Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 17/27] phy: rockchip: usbdp: Register DP aux bridge Sebastian Reichel
` (10 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
Use FIELD_PREP_WM16() helpers to simplify the DP lane selection
logic.
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 28 +++++++---------------------
1 file changed, 7 insertions(+), 21 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 1bae8172d1fe..71ee2f4faf0b 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -553,30 +553,16 @@ static void rk_udphy_usb_bvalid_enable(struct rk_udphy *udphy, u8 enable)
static void rk_udphy_dp_lane_select(struct rk_udphy *udphy)
{
const struct rk_udphy_cfg *cfg = udphy->cfgs;
- u32 value = 0;
-
- switch (udphy->dp_lanes) {
- case 4:
- value |= 3 << udphy->dp_lane_sel[3] * 2;
- value |= 2 << udphy->dp_lane_sel[2] * 2;
- fallthrough;
-
- case 2:
- value |= 1 << udphy->dp_lane_sel[1] * 2;
- fallthrough;
+ u32 value = FIELD_PREP_WM16(DP_LANE_SEL_ALL, 0);
+ int i;
- case 1:
- value |= 0 << udphy->dp_lane_sel[0] * 2;
- break;
+ for (i = 0; i < udphy->dp_lanes; i++)
+ value |= field_prep(DP_LANE_SEL_N(udphy->dp_lane_sel[i]), i);
- default:
- break;
- }
+ value |= FIELD_PREP_WM16(DP_AUX_DIN_SEL, udphy->dp_aux_din_sel);
+ value |= FIELD_PREP_WM16(DP_AUX_DOUT_SEL, udphy->dp_aux_dout_sel);
- regmap_write(udphy->vogrf, cfg->vogrfcfg[udphy->id].dp_lane_reg,
- ((DP_AUX_DIN_SEL | DP_AUX_DOUT_SEL | DP_LANE_SEL_ALL) << 16) |
- FIELD_PREP(DP_AUX_DIN_SEL, udphy->dp_aux_din_sel) |
- FIELD_PREP(DP_AUX_DOUT_SEL, udphy->dp_aux_dout_sel) | value);
+ regmap_write(udphy->vogrf, cfg->vogrfcfg[udphy->id].dp_lane_reg, value);
}
static void rk_udphy_dp_lane_enable(struct rk_udphy *udphy, int dp_lanes)
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 17/27] phy: rockchip: usbdp: Register DP aux bridge
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (15 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 16/27] phy: rockchip: usbdp: Cleanup DP lane selection function Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 18/27] phy: rockchip: usbdp: Drop DP HPD handling Sebastian Reichel
` (9 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
Add support to use USB-C connectors with the DP altmode helper code on
devicetree based platforms. To get this working there must be a DRM
bridge chain from the DisplayPort controller to the USB-C connector.
E.g. on Rockchip RK3576:
root@rk3576 # cat /sys/kernel/debug/dri/0/encoder-0/bridges
bridge[0]: dw_dp_bridge_funcs
refcount: 7
type: [10] DP
OF: /soc/dp@27e40000:rockchip,rk3576-dp
ops: [0x47] detect edid hpd
bridge[1]: drm_aux_bridge_funcs
refcount: 4
type: [0] Unknown
OF: /soc/phy@2b010000:rockchip,rk3576-usbdp-phy
ops: [0x0]
bridge[2]: drm_aux_hpd_bridge_funcs
refcount: 5
type: [10] DP
OF: /soc/i2c@2ac50000/typec-portc@22/connector:usb-c-connector
ops: [0x4] hpd
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/Kconfig | 2 ++
drivers/phy/rockchip/phy-rockchip-usbdp.c | 14 ++++++++++++++
2 files changed, 16 insertions(+)
diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig
index 14698571b607..39759bb2fa1d 100644
--- a/drivers/phy/rockchip/Kconfig
+++ b/drivers/phy/rockchip/Kconfig
@@ -136,8 +136,10 @@ config PHY_ROCKCHIP_USBDP
tristate "Rockchip USBDP COMBO PHY Driver"
depends on ARCH_ROCKCHIP && OF
depends on TYPEC
+ depends on DRM || DRM=n
select GENERIC_PHY
select USB_COMMON
+ select DRM_AUX_BRIDGE if DRM_BRIDGE
help
Enable this to support the Rockchip USB3.0/DP combo PHY with
Samsung IP block. This is required for USB3 support on RK3588.
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 71ee2f4faf0b..7bac3f14d750 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -6,6 +6,7 @@
* Copyright (C) 2024 Collabora Ltd
*/
+#include <drm/bridge/aux-bridge.h>
#include <dt-bindings/phy/phy.h>
#include <linux/bitfield.h>
#include <linux/bits.h>
@@ -1444,6 +1445,7 @@ static int rk_udphy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct phy_provider *phy_provider;
+ struct fwnode_handle *dp_aux_ep;
struct resource *res;
struct rk_udphy *udphy;
void __iomem *base;
@@ -1502,6 +1504,18 @@ static int rk_udphy_probe(struct platform_device *pdev)
return ret;
}
+ /*
+ * Only register the DRM bridge, if the DP aux channel is connected.
+ * Some boards use the USBDP PHY only for its USB3 capabilities.
+ */
+ dp_aux_ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 3, 0, 0);
+ if (dp_aux_ep) {
+ ret = drm_aux_bridge_register(dev);
+ fwnode_handle_put(dp_aux_ep);
+ if (ret)
+ return ret;
+ }
+
udphy->phy_u3 = devm_phy_create(dev, dev->of_node, &rk_udphy_usb3_phy_ops);
if (IS_ERR(udphy->phy_u3)) {
ret = PTR_ERR(udphy->phy_u3);
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 18/27] phy: rockchip: usbdp: Drop DP HPD handling
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (16 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 17/27] phy: rockchip: usbdp: Register DP aux bridge Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 19/27] phy: rockchip: usbdp: Rename mode_change to phy_needs_reinit Sebastian Reichel
` (8 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
Drop the HPD handling logic from the USBDP PHY. The registers involved
require the display controller power domain being enabled and thus the
HPD signal should be handled by the displayport controller itself.
Apart from that the HPD handling as it is done here is incorrect and
misses hotplug events happening after the USB-C connector (e.g. when
a USB-C to HDMI adapter is involved and the HDMI cable is replugged).
Proper USB-C DP HPD support requires some restructuring of the DP
controller driver, which will happen independent of this patch. The
mainline kernel does not yet support USB-C DP AltMode on RK3588 and
RK3576, so it is fine to drop this code without adding the counterpart
in the DRM in an atomic change.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 85 ++++---------------------------
1 file changed, 9 insertions(+), 76 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 7bac3f14d750..8b5b188fd121 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -128,7 +128,6 @@ struct rk_udphy_grf_cfg {
struct rk_udphy_vogrf_cfg {
/* vo-grf */
- struct rk_udphy_grf_reg hpd_trigger;
u32 dp_lane_reg;
};
@@ -186,14 +185,11 @@ struct rk_udphy {
u32 dp_lane_sel[4];
u32 dp_aux_dout_sel;
u32 dp_aux_din_sel;
- bool dp_sink_hpd_sel;
- bool dp_sink_hpd_cfg;
unsigned int link_rate;
unsigned int lanes;
u8 bw;
int id;
- bool dp_in_use;
int dp_lanes;
/* PHY const config */
@@ -582,19 +578,6 @@ 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_dp_hpd_event_trigger(struct rk_udphy *udphy, bool hpd)
-{
- const struct rk_udphy_cfg *cfg = udphy->cfgs;
-
- udphy->dp_sink_hpd_sel = true;
- udphy->dp_sink_hpd_cfg = hpd;
-
- if (!udphy->dp_in_use)
- return;
-
- rk_udphy_grfreg_write(udphy->vogrf, &cfg->vogrfcfg[udphy->id].hpd_trigger, hpd);
-}
-
static void rk_udphy_mode_set(struct rk_udphy *udphy, u8 mode)
{
if (udphy->mode == mode)
@@ -1030,29 +1013,6 @@ static void rk_udphy_power_off(struct rk_udphy *udphy, u8 mode)
rk_udphy_disable(udphy);
}
-static int rk_udphy_dp_phy_init(struct phy *phy)
-{
- struct rk_udphy *udphy = phy_get_drvdata(phy);
-
- mutex_lock(&udphy->mutex);
-
- udphy->dp_in_use = true;
-
- mutex_unlock(&udphy->mutex);
-
- return 0;
-}
-
-static int rk_udphy_dp_phy_exit(struct phy *phy)
-{
- struct rk_udphy *udphy = phy_get_drvdata(phy);
-
- mutex_lock(&udphy->mutex);
- udphy->dp_in_use = false;
- mutex_unlock(&udphy->mutex);
- return 0;
-}
-
static int rk_udphy_dp_phy_power_on(struct phy *phy)
{
struct rk_udphy *udphy = phy_get_drvdata(phy);
@@ -1284,8 +1244,6 @@ static int rk_udphy_dp_phy_configure(struct phy *phy,
}
static const struct phy_ops rk_udphy_dp_phy_ops = {
- .init = rk_udphy_dp_phy_init,
- .exit = rk_udphy_dp_phy_exit,
.power_on = rk_udphy_dp_phy_power_on,
.power_off = rk_udphy_dp_phy_power_off,
.configure = rk_udphy_dp_phy_configure,
@@ -1339,6 +1297,14 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
struct rk_udphy *udphy = typec_mux_get_drvdata(mux);
u8 mode;
+ /*
+ * Ignore mux events not involving DP AltMode, because
+ * the mode field is being reused, e.g. state->mode == 4
+ * could be either TYPEC_MODE_USB4 or TYPEC_DP_STATE_C.
+ */
+ if (!state->alt || state->alt->svid != USB_TYPEC_DP_SID)
+ return 0;
+
mutex_lock(&udphy->mutex);
switch (state->mode) {
@@ -1370,22 +1336,7 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
break;
}
- if (state->alt && state->alt->svid == USB_TYPEC_DP_SID) {
- struct typec_displayport_data *data = state->data;
-
- if (!data) {
- rk_udphy_dp_hpd_event_trigger(udphy, false);
- } else if (data->status & DP_STATUS_IRQ_HPD) {
- rk_udphy_dp_hpd_event_trigger(udphy, false);
- usleep_range(750, 800);
- rk_udphy_dp_hpd_event_trigger(udphy, true);
- } else if (data->status & DP_STATUS_HPD_STATE) {
- rk_udphy_mode_set(udphy, mode);
- rk_udphy_dp_hpd_event_trigger(udphy, true);
- } else {
- rk_udphy_dp_hpd_event_trigger(udphy, false);
- }
- }
+ rk_udphy_mode_set(udphy, mode);
mutex_unlock(&udphy->mutex);
return 0;
@@ -1541,20 +1492,6 @@ static int rk_udphy_probe(struct platform_device *pdev)
return 0;
}
-static int __maybe_unused rk_udphy_resume(struct device *dev)
-{
- struct rk_udphy *udphy = dev_get_drvdata(dev);
-
- if (udphy->dp_sink_hpd_sel)
- rk_udphy_dp_hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg);
-
- return 0;
-}
-
-static const struct dev_pm_ops rk_udphy_pm_ops = {
- SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, rk_udphy_resume)
-};
-
static const char * const rk_udphy_rst_list[] = {
"init", "cmn", "lane", "pcs_apb", "pma_apb"
};
@@ -1578,7 +1515,6 @@ static const struct rk_udphy_cfg rk3576_udphy_cfgs = {
},
.vogrfcfg = {
{
- .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0000, 11, 10, 1, 3),
.dp_lane_reg = 0x0000,
},
},
@@ -1619,11 +1555,9 @@ static const struct rk_udphy_cfg rk3588_udphy_cfgs = {
},
.vogrfcfg = {
{
- .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0000, 11, 10, 1, 3),
.dp_lane_reg = 0x0000,
},
{
- .hpd_trigger = RK_UDPHY_GEN_GRF_REG(0x0008, 11, 10, 1, 3),
.dp_lane_reg = 0x0008,
},
},
@@ -1659,7 +1593,6 @@ static struct platform_driver rk_udphy_driver = {
.driver = {
.name = "rockchip-usbdp-phy",
.of_match_table = rk_udphy_dt_match,
- .pm = &rk_udphy_pm_ops,
},
};
module_platform_driver(rk_udphy_driver);
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 19/27] phy: rockchip: usbdp: Rename mode_change to phy_needs_reinit
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (17 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 18/27] phy: rockchip: usbdp: Drop DP HPD handling Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 20/27] phy: rockchip: usbdp: Re-init the PHY on orientation change Sebastian Reichel
` (7 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
Right now the mode_change property is set whenever the mode changes
between USB-only, DP-only and USB-DP. It is needed, because on any
mode change the PHY needs to be re-initialized. Apparently at least
DP also requires a re-init when the cable orientation is changed,
which is currently not being done (except when the orientation switch
also involves a mode change). Prepare for this by renaming mode_change
to phy_needs_reinit.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 8b5b188fd121..b08f0c142b0d 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -171,7 +171,7 @@ struct rk_udphy {
/* PHY status management */
bool flip;
- bool mode_change;
+ bool phy_needs_reinit;
u8 mode;
u8 status;
@@ -583,7 +583,7 @@ static void rk_udphy_mode_set(struct rk_udphy *udphy, u8 mode)
if (udphy->mode == mode)
return;
- udphy->mode_change = true;
+ udphy->phy_needs_reinit = true;
udphy->mode = mode;
}
@@ -981,15 +981,15 @@ static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode)
if (udphy->mode & UDPHY_MODE_USB)
rk_udphy_u3_port_disable(udphy, false);
- udphy->mode_change = false;
- } else if (udphy->mode_change) {
+ udphy->phy_needs_reinit = false;
+ } else if (udphy->phy_needs_reinit) {
if (udphy->mode == UDPHY_MODE_DP)
rk_udphy_u3_port_disable(udphy, true);
ret = rk_udphy_init(udphy);
if (ret)
return ret;
- udphy->mode_change = false;
+ udphy->phy_needs_reinit = false;
}
udphy->status |= mode;
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 20/27] phy: rockchip: usbdp: Re-init the PHY on orientation change
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (18 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 19/27] phy: rockchip: usbdp: Rename mode_change to phy_needs_reinit Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 18:09 ` sashiko-bot
2026-06-25 17:39 ` [PATCH v7 21/27] phy: rockchip: usbdp: Factor out lane_mux_sel setup Sebastian Reichel
` (6 subsequent siblings)
26 siblings, 1 reply; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
Changing the cable orientation reconfigures the lane muxing, which
requires re-initializing the PHY. Without this DP functionality
breaks, if the cable is re-plugged with swapped orientation.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index b08f0c142b0d..3fa97a8c2555 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -625,6 +625,7 @@ static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw,
enum typec_orientation orien)
{
struct rk_udphy *udphy = typec_switch_get_drvdata(sw);
+ bool flipped = orien == TYPEC_ORIENTATION_REVERSE;
mutex_lock(&udphy->mutex);
@@ -636,7 +637,10 @@ static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw,
goto unlock_ret;
}
- udphy->flip = orien == TYPEC_ORIENTATION_REVERSE;
+ if (udphy->flip != flipped)
+ udphy->phy_needs_reinit = true;
+
+ udphy->flip = flipped;
rk_udphy_set_typec_default_mapping(udphy);
rk_udphy_usb_bvalid_enable(udphy, true);
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* Re: [PATCH v7 20/27] phy: rockchip: usbdp: Re-init the PHY on orientation change
2026-06-25 17:39 ` [PATCH v7 20/27] phy: rockchip: usbdp: Re-init the PHY on orientation change Sebastian Reichel
@ 2026-06-25 18:09 ` sashiko-bot
0 siblings, 0 replies; 37+ messages in thread
From: sashiko-bot @ 2026-06-25 18:09 UTC (permalink / raw)
To: Sebastian Reichel
Cc: devicetree, conor+dt, olteanv, neil.armstrong, vkoul, linux-phy,
robh
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The patch attempts to fix PHY lane muxing on cable orientation changes by setting `phy_needs_reinit = true`, but this fails to re-initialize the PHY for USB3-only connections, leaving USB3 broken on reverse orientation plugs or flips.
--
commit d1dadcaee0ea260b3047754297edae7462107b62
Author: Sebastian Reichel <sebastian.reichel@collabora.com>
phy: rockchip: usbdp: Re-init the PHY on orientation change
This commit changes the cable orientation logic to reconfigure lane muxing
and sets a flag to re-initialize the PHY if the cable is re-plugged with a
swapped orientation.
> diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> index b08f0c142b0d2..3fa97a8c2555a 100644
> --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
> +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
[ ... ]
> @@ -636,7 +637,10 @@ static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw,
> goto unlock_ret;
> }
>
> - udphy->flip = orien == TYPEC_ORIENTATION_REVERSE;
> + if (udphy->flip != flipped)
> + udphy->phy_needs_reinit = true;
> +
> + udphy->flip = flipped;
[Severity: High]
Does setting phy_needs_reinit here actually trigger a re-initialization for
USB3-only connections?
When the Type-C controller detects a cable orientation change, it calls
rk_udphy_orien_sw_set(). The driver updates udphy->flip and defers hardware
re-initialization until rk_udphy_power_on() is called.
However, for USB3-only connections, DWC3 does not cycle phy_init() or
phy_power_on() on a simple replug since the PHY remains powered. This means
rk_udphy_power_on() is never invoked and the PHY is never re-initialized with
the new lane muxing, which could cause USB 3.0 link training to fail when a
cable is flipped.
A later patch in the series (phy: rockchip: usbdp: Properly handle
TYPEC_STATE_SAFE and TYPEC_STATE_USB) attempts to address Type-C state
changes, but its logic appears to abort for both TYPEC_STATE_USB and modal
states. Even if corrected, its transition check would be false for a simple
cable flip that remains in USB mode, meaning this issue would persist.
> rk_udphy_set_typec_default_mapping(udphy);
> rk_udphy_usb_bvalid_enable(udphy, true);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260625-rockchip-usbdp-cleanup-v7-0-38eb3cf654fd@collabora.com?part=20
^ permalink raw reply [flat|nested] 37+ messages in thread
* [PATCH v7 21/27] phy: rockchip: usbdp: Factor out lane_mux_sel setup
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (19 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 20/27] phy: rockchip: usbdp: Re-init the PHY on orientation change Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 22/27] phy: rockchip: usbdp: Properly handle TYPEC_STATE_SAFE and TYPEC_STATE_USB Sebastian Reichel
` (5 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
Avoid describing the USB+DP lane_mux_sel logic twice by introducing
a helper function to reduce code duplication.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 81 +++++++++++++++----------------
1 file changed, 40 insertions(+), 41 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 3fa97a8c2555..0bcaf54c5645 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -587,6 +587,42 @@ static void rk_udphy_mode_set(struct rk_udphy *udphy, u8 mode)
udphy->mode = mode;
}
+static void rk_udphy_set_typec_state(struct rk_udphy *udphy, unsigned long state)
+{
+ u8 mode;
+
+ switch (state) {
+ case TYPEC_DP_STATE_C:
+ case TYPEC_DP_STATE_E:
+ 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;
+ mode = UDPHY_MODE_DP;
+ udphy->dp_lanes = 4;
+ break;
+
+ case TYPEC_DP_STATE_D:
+ default:
+ if (udphy->flip) {
+ 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_USB;
+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB;
+ } else {
+ udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB;
+ udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB;
+ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP;
+ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP;
+ }
+ mode = UDPHY_MODE_DP_USB;
+ udphy->dp_lanes = 2;
+ break;
+ }
+
+ rk_udphy_mode_set(udphy, mode);
+}
+
static void rk_udphy_set_typec_default_mapping(struct rk_udphy *udphy)
{
if (udphy->flip) {
@@ -594,10 +630,6 @@ static void rk_udphy_set_typec_default_mapping(struct rk_udphy *udphy)
udphy->dp_lane_sel[1] = 1;
udphy->dp_lane_sel[2] = 3;
udphy->dp_lane_sel[3] = 2;
- 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_USB;
- udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB;
udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_INVERT;
udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_INVERT;
gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 1);
@@ -607,18 +639,14 @@ static void rk_udphy_set_typec_default_mapping(struct rk_udphy *udphy)
udphy->dp_lane_sel[1] = 3;
udphy->dp_lane_sel[2] = 1;
udphy->dp_lane_sel[3] = 0;
- udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB;
- udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB;
- udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP;
- udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP;
udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_NORMAL;
udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_NORMAL;
gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0);
gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 1);
}
- rk_udphy_mode_set(udphy, UDPHY_MODE_DP_USB);
- udphy->dp_lanes = 2;
+ /* default to USB3 + DP as 4 lane USB is not supported */
+ rk_udphy_set_typec_state(udphy, TYPEC_DP_STATE_D);
}
static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw,
@@ -1299,7 +1327,6 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
struct typec_mux_state *state)
{
struct rk_udphy *udphy = typec_mux_get_drvdata(mux);
- u8 mode;
/*
* Ignore mux events not involving DP AltMode, because
@@ -1311,38 +1338,10 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
mutex_lock(&udphy->mutex);
- switch (state->mode) {
- case TYPEC_DP_STATE_C:
- case TYPEC_DP_STATE_E:
- 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;
- mode = UDPHY_MODE_DP;
- udphy->dp_lanes = 4;
- break;
-
- case TYPEC_DP_STATE_D:
- default:
- if (udphy->flip) {
- 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_USB;
- udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB;
- } else {
- udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB;
- udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB;
- udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP;
- udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP;
- }
- mode = UDPHY_MODE_DP_USB;
- udphy->dp_lanes = 2;
- break;
- }
-
- rk_udphy_mode_set(udphy, mode);
+ rk_udphy_set_typec_state(udphy, state->mode);
mutex_unlock(&udphy->mutex);
+
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 22/27] phy: rockchip: usbdp: Properly handle TYPEC_STATE_SAFE and TYPEC_STATE_USB
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (20 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 21/27] phy: rockchip: usbdp: Factor out lane_mux_sel setup Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 18:11 ` sashiko-bot
2026-06-25 17:39 ` [PATCH v7 23/27] phy: rockchip: usbdp: Use guard functions for mutex Sebastian Reichel
` (4 subsequent siblings)
26 siblings, 1 reply; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel, Sashiko
Handle TYPEC_STATE_SAFE and TYPEC_STATE_USB Type-C state events,
so that the muxing is properly updated when exiting DP AltMode.
Fixes: 2f70bbddeb45 ("phy: rockchip: add usbdp combo phy driver")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/message/20260619155020.CC7361F000E9%40smtp.kernel.org
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 0bcaf54c5645..0119b6229b0a 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -1329,11 +1329,12 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
struct rk_udphy *udphy = typec_mux_get_drvdata(mux);
/*
- * Ignore mux events not involving DP AltMode, because
- * the mode field is being reused, e.g. state->mode == 4
- * could be either TYPEC_MODE_USB4 or TYPEC_DP_STATE_C.
+ * Ignore mux events not involving Safe State, USB State or DP AltMode,
+ * because the mode field is being reused, e.g. state->mode == 4 could
+ * be either TYPEC_MODE_USB4 or TYPEC_DP_STATE_C.
*/
- if (!state->alt || state->alt->svid != USB_TYPEC_DP_SID)
+ if (state->mode >= TYPEC_STATE_MODAL || !state->alt ||
+ state->alt->svid != USB_TYPEC_DP_SID)
return 0;
mutex_lock(&udphy->mutex);
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* Re: [PATCH v7 22/27] phy: rockchip: usbdp: Properly handle TYPEC_STATE_SAFE and TYPEC_STATE_USB
2026-06-25 17:39 ` [PATCH v7 22/27] phy: rockchip: usbdp: Properly handle TYPEC_STATE_SAFE and TYPEC_STATE_USB Sebastian Reichel
@ 2026-06-25 18:11 ` sashiko-bot
0 siblings, 0 replies; 37+ messages in thread
From: sashiko-bot @ 2026-06-25 18:11 UTC (permalink / raw)
To: Sebastian Reichel
Cc: olteanv, robh, neil.armstrong, linux-phy, devicetree, vkoul,
conor+dt
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [High] A critical boolean logic error in `rk_udphy_typec_mux_set` incorrectly uses logical OR (`||`), causing all valid Type-C events to be ignored and breaking the state machine.
Pre-existing issues:
- [High] NULL pointer dereference when handling non-DP accessory modes (like Audio Accessory) in Type-C mux drivers.
--
commit b36f3de7b0f44156b05e5cda72d2bdd174f98299
Author: Sebastian Reichel <sebastian.reichel@collabora.com>
phy: rockchip: usbdp: Properly handle TYPEC_STATE_SAFE and TYPEC_STATE_USB
This patch handles TYPEC_STATE_SAFE and TYPEC_STATE_USB Type-C state events
so that the muxing is properly updated when exiting DP AltMode.
Fixes: 2f70bbddeb45 ("phy: rockchip: add usbdp combo phy driver")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/message/20260619155020.CC7361F000E9%40smtp.kernel.org
> diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> index 0bcaf54c5645d..0119b6229b0a9 100644
> --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
> +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> @@ -1329,11 +1329,12 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
> struct rk_udphy *udphy = typec_mux_get_drvdata(mux);
>
> /*
> - * Ignore mux events not involving DP AltMode, because
> - * the mode field is being reused, e.g. state->mode == 4
> - * could be either TYPEC_MODE_USB4 or TYPEC_DP_STATE_C.
> + * Ignore mux events not involving Safe State, USB State or DP AltMode,
> + * because the mode field is being reused, e.g. state->mode == 4 could
> + * be either TYPEC_MODE_USB4 or TYPEC_DP_STATE_C.
> */
> - if (!state->alt || state->alt->svid != USB_TYPEC_DP_SID)
> + if (state->mode >= TYPEC_STATE_MODAL || !state->alt ||
> + state->alt->svid != USB_TYPEC_DP_SID)
> return 0;
[Severity: High]
Does this conditional unintentionally ignore all valid states by using
logical OR instead of logical AND?
If a DP AltMode event is passed, state->mode >= TYPEC_STATE_MODAL evaluates
to true, causing an early return.
If a Safe State or USB State event is passed, state->alt is NULL, which also
causes an early return.
This appears to short-circuit and return 0 for all expected Type-C muxing
events, breaking the state machine.
[Severity: High]
This is a pre-existing issue, but can accessory modes trigger a NULL pointer
dereference in other Type-C mux drivers?
When the Type-C port is set to an accessory mode like TYPEC_MODE_AUDIO,
state->mode >= TYPEC_STATE_MODAL evaluates to true, but state->alt is
initialized to NULL.
In drivers/usb/typec/mux/it5205.c:it5205_mux_set():
if (state->mode >= TYPEC_STATE_MODAL &&
state->alt->svid != USB_TYPEC_DP_SID)
return -EINVAL;
And similarly in drivers/usb/typec/mux/tusb1046.c:tusb1046_mux_set():
if (state->mode >= TYPEC_STATE_MODAL &&
state->alt->svid != USB_TYPEC_DP_SID)
return -EINVAL;
Does this condition dereference state->alt without checking if it is NULL
when a non-DP modal device is plugged in?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260625-rockchip-usbdp-cleanup-v7-0-38eb3cf654fd@collabora.com?part=22
^ permalink raw reply [flat|nested] 37+ messages in thread
* [PATCH v7 23/27] phy: rockchip: usbdp: Use guard functions for mutex
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (21 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 22/27] phy: rockchip: usbdp: Properly handle TYPEC_STATE_SAFE and TYPEC_STATE_USB Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 24/27] phy: rockchip: usbdp: Support going from DP-only mode to USB mode Sebastian Reichel
` (3 subsequent siblings)
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
Convert the driver to use guard functions for mutex handling as
a small cleanup. There is a small functional change in the DP PHY
power up function, which no longer sleeps if the internal powerup
code returns an error. This is not a problem as the sleep is only
relevant for successful power-up.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 54 +++++++++++++------------------
1 file changed, 23 insertions(+), 31 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 0119b6229b0a..6f3184011e5f 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -10,6 +10,7 @@
#include <dt-bindings/phy/phy.h>
#include <linux/bitfield.h>
#include <linux/bits.h>
+#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
@@ -655,14 +656,15 @@ static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw,
struct rk_udphy *udphy = typec_switch_get_drvdata(sw);
bool flipped = orien == TYPEC_ORIENTATION_REVERSE;
- mutex_lock(&udphy->mutex);
+ guard(mutex)(&udphy->mutex);
if (orien == TYPEC_ORIENTATION_NONE) {
gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0);
gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0);
/* unattached */
rk_udphy_usb_bvalid_enable(udphy, false);
- goto unlock_ret;
+
+ return 0;
}
if (udphy->flip != flipped)
@@ -672,8 +674,6 @@ static int rk_udphy_orien_sw_set(struct typec_switch_dev *sw,
rk_udphy_set_typec_default_mapping(udphy);
rk_udphy_usb_bvalid_enable(udphy, true);
-unlock_ret:
- mutex_unlock(&udphy->mutex);
return 0;
}
@@ -1050,26 +1050,25 @@ static int rk_udphy_dp_phy_power_on(struct phy *phy)
struct rk_udphy *udphy = phy_get_drvdata(phy);
int ret;
- mutex_lock(&udphy->mutex);
+ scoped_guard(mutex, &udphy->mutex) {
+ phy_set_bus_width(phy, udphy->dp_lanes);
- phy_set_bus_width(phy, udphy->dp_lanes);
-
- ret = rk_udphy_power_on(udphy, UDPHY_MODE_DP);
- if (ret)
- goto unlock;
+ ret = rk_udphy_power_on(udphy, UDPHY_MODE_DP);
+ if (ret)
+ return ret;
- rk_udphy_dp_lane_enable(udphy, udphy->dp_lanes);
+ rk_udphy_dp_lane_enable(udphy, udphy->dp_lanes);
- rk_udphy_dp_lane_select(udphy);
+ rk_udphy_dp_lane_select(udphy);
+ }
-unlock:
- mutex_unlock(&udphy->mutex);
/*
* If data send by aux channel too fast after phy power on,
* the aux may be not ready which will cause aux error. Adding
* delay to avoid this issue.
*/
usleep_range(10000, 11000);
+
return ret;
}
@@ -1077,10 +1076,10 @@ static int rk_udphy_dp_phy_power_off(struct phy *phy)
{
struct rk_udphy *udphy = phy_get_drvdata(phy);
- mutex_lock(&udphy->mutex);
+ guard(mutex)(&udphy->mutex);
+
rk_udphy_dp_lane_enable(udphy, 0);
rk_udphy_power_off(udphy, UDPHY_MODE_DP);
- mutex_unlock(&udphy->mutex);
return 0;
}
@@ -1285,35 +1284,30 @@ static const struct phy_ops rk_udphy_dp_phy_ops = {
static int rk_udphy_usb3_phy_init(struct phy *phy)
{
struct rk_udphy *udphy = phy_get_drvdata(phy);
- int ret = 0;
- mutex_lock(&udphy->mutex);
+ guard(mutex)(&udphy->mutex);
+
/* DP only or high-speed, disable U3 port */
if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs) {
rk_udphy_u3_port_disable(udphy, true);
- goto unlock;
+ return 0;
}
- ret = rk_udphy_power_on(udphy, UDPHY_MODE_USB);
-
-unlock:
- mutex_unlock(&udphy->mutex);
- return ret;
+ return rk_udphy_power_on(udphy, UDPHY_MODE_USB);
}
static int rk_udphy_usb3_phy_exit(struct phy *phy)
{
struct rk_udphy *udphy = phy_get_drvdata(phy);
- mutex_lock(&udphy->mutex);
+ guard(mutex)(&udphy->mutex);
+
/* DP only or high-speed */
if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs)
- goto unlock;
+ return 0;
rk_udphy_power_off(udphy, UDPHY_MODE_USB);
-unlock:
- mutex_unlock(&udphy->mutex);
return 0;
}
@@ -1337,12 +1331,10 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
state->alt->svid != USB_TYPEC_DP_SID)
return 0;
- mutex_lock(&udphy->mutex);
+ guard(mutex)(&udphy->mutex);
rk_udphy_set_typec_state(udphy, state->mode);
- mutex_unlock(&udphy->mutex);
-
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 24/27] phy: rockchip: usbdp: Support going from DP-only mode to USB mode
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (22 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 23/27] phy: rockchip: usbdp: Use guard functions for mutex Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 18:12 ` sashiko-bot
2026-06-25 17:39 ` [PATCH v7 25/27] phy: rockchip: usbdp: Hold mutex in DP PHY configure Sebastian Reichel
` (2 subsequent siblings)
26 siblings, 1 reply; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
When a USB-C adapter, which maps all Superspeed lanes to DP is plugged
in, the USB support is disabled in the PHY. When the adapter is
unplugged and a different adapter with USB functionality is plugged in
afterwards, USB functionality is not restored as the USB controller
keeps the PHY enabled for the entire time.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 6f3184011e5f..182141837596 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -178,6 +178,7 @@ struct rk_udphy {
/* utilized for USB */
bool hs; /* flag for high-speed */
+ bool usb_in_use;
/* utilized for DP */
struct gpio_desc *sbu1_dc_gpio;
@@ -1021,6 +1022,10 @@ static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode)
ret = rk_udphy_init(udphy);
if (ret)
return ret;
+
+ if (udphy->mode & UDPHY_MODE_USB)
+ rk_udphy_u3_port_disable(udphy, false);
+
udphy->phy_needs_reinit = false;
}
@@ -1284,6 +1289,7 @@ static const struct phy_ops rk_udphy_dp_phy_ops = {
static int rk_udphy_usb3_phy_init(struct phy *phy)
{
struct rk_udphy *udphy = phy_get_drvdata(phy);
+ int ret;
guard(mutex)(&udphy->mutex);
@@ -1293,7 +1299,13 @@ static int rk_udphy_usb3_phy_init(struct phy *phy)
return 0;
}
- return rk_udphy_power_on(udphy, UDPHY_MODE_USB);
+ ret = rk_udphy_power_on(udphy, UDPHY_MODE_USB);
+ if (ret)
+ return ret;
+
+ udphy->usb_in_use = true;
+
+ return 0;
}
static int rk_udphy_usb3_phy_exit(struct phy *phy)
@@ -1302,6 +1314,8 @@ static int rk_udphy_usb3_phy_exit(struct phy *phy)
guard(mutex)(&udphy->mutex);
+ udphy->usb_in_use = false;
+
/* DP only or high-speed */
if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs)
return 0;
@@ -1321,6 +1335,7 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
struct typec_mux_state *state)
{
struct rk_udphy *udphy = typec_mux_get_drvdata(mux);
+ u8 old_mode;
/*
* Ignore mux events not involving Safe State, USB State or DP AltMode,
@@ -1333,8 +1348,20 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
guard(mutex)(&udphy->mutex);
+ old_mode = udphy->mode;
+
rk_udphy_set_typec_state(udphy, state->mode);
+ /*
+ * If the new mode includes USB but the old one didn't (e.g. leaving
+ * DP-only), and the USB PHY was already initialized by the USB
+ * controller, we need to power on the USB side now since no
+ * subsequent phy_init call will come from the controller.
+ */
+ if ((udphy->mode & UDPHY_MODE_USB) && !(old_mode & UDPHY_MODE_USB) &&
+ udphy->usb_in_use && !udphy->hs)
+ return rk_udphy_power_on(udphy, UDPHY_MODE_USB);
+
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* Re: [PATCH v7 24/27] phy: rockchip: usbdp: Support going from DP-only mode to USB mode
2026-06-25 17:39 ` [PATCH v7 24/27] phy: rockchip: usbdp: Support going from DP-only mode to USB mode Sebastian Reichel
@ 2026-06-25 18:12 ` sashiko-bot
0 siblings, 0 replies; 37+ messages in thread
From: sashiko-bot @ 2026-06-25 18:12 UTC (permalink / raw)
To: Sebastian Reichel
Cc: linux-phy, robh, vkoul, devicetree, neil.armstrong, olteanv,
conor+dt
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] The `typec_mux_set` early return condition is a tautology, causing the function to always return 0 and ignore all events.
- [High] The `usb_in_use` flag fails to record the USB controller's intent if `phy_init` is called while a DP-only adapter is plugged in.
- [High] The fallback USB power-on logic in `rk_udphy_typec_mux_set` will never trigger due to mode transition interference from orientation switch callbacks.
Pre-existing issues:
- [High] The `UDPHY_MODE_USB` state bit is leaked in `udphy->status` if the USB controller unbinds/exits while the PHY is in DP-only mode.
--
commit b29d116f72e458e2aa19213a694463c70672b033
Author: Sebastian Reichel <sebastian.reichel@collabora.com>
phy: rockchip: usbdp: Support going from DP-only mode to USB mode
When a USB-C adapter mapping all Superspeed lanes to DP is plugged in,
USB support is disabled in the PHY. This patch tracks USB usage and
powers on the USB PHY in the Type-C mux set callback to ensure USB
functionality is restored when switching to a USB-capable adapter.
> diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
> index 6f3184011e5f2..1821418375968 100644
> --- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
> +++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
[ ... ]
> @@ -1293,7 +1299,13 @@ static int rk_udphy_usb3_phy_init(struct phy *phy)
> return 0;
> }
>
> - return rk_udphy_power_on(udphy, UDPHY_MODE_USB);
> + ret = rk_udphy_power_on(udphy, UDPHY_MODE_USB);
> + if (ret)
> + return ret;
> +
> + udphy->usb_in_use = true;
> +
> + return 0;
> }
[Severity: High]
If the USB controller probes and calls rk_udphy_usb3_phy_init() while a
DP-only adapter is physically connected, udphy->mode will lack
UDPHY_MODE_USB. The early return right before this will skip setting
udphy->usb_in_use = true.
Will this cause the fallback logic introduced below to fail when later
switched to a USB-capable adapter?
> static int rk_udphy_usb3_phy_exit(struct phy *phy)
> @@ -1302,6 +1314,8 @@ static int rk_udphy_usb3_phy_exit(struct phy *phy)
>
> guard(mutex)(&udphy->mutex);
>
> + udphy->usb_in_use = false;
> +
> /* DP only or high-speed */
> if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs)
> return 0;
>
> rk_udphy_power_off(udphy, UDPHY_MODE_USB);
[Severity: High]
This is a pre-existing issue, but does this early return bypass state
cleanup if the USB controller unbinds while the PHY is in DP-only mode?
If udphy->mode lacks UDPHY_MODE_USB, rk_udphy_power_off() is skipped, which
permanently leaves UDPHY_MODE_USB set in udphy->status and leaks hardware
clocks and resets.
> @@ -1321,6 +1335,7 @@ static int rk_udphy_typec_mux_set(struct typec_mux_dev *mux,
> struct typec_mux_state *state)
> {
> struct rk_udphy *udphy = typec_mux_get_drvdata(mux);
> + u8 old_mode;
>
> /*
> * Ignore mux events not involving Safe State, USB State or DP AltMode,
> * because the mode field is being reused, e.g. state->mode == 4 could
> * be either TYPEC_MODE_USB4 or TYPEC_DP_STATE_C.
> */
> if (state->mode >= TYPEC_STATE_MODAL || !state->alt ||
> state->alt->svid != USB_TYPEC_DP_SID)
> return 0;
[Severity: High]
Is this early return condition a tautology that drops all events?
For Safe and USB states, state->alt is NULL, so !state->alt evaluates to
true. For DP AltMode states, state->mode >= TYPEC_STATE_MODAL evaluates to
true. Since these use logical OR, the function will always return 0.
>
> guard(mutex)(&udphy->mutex);
>
> + old_mode = udphy->mode;
> +
> rk_udphy_set_typec_state(udphy, state->mode);
>
> + /*
> + * If the new mode includes USB but the old one didn't (e.g. leaving
> + * DP-only), and the USB PHY was already initialized by the USB
> + * controller, we need to power on the USB side now since no
> + * subsequent phy_init call will come from the controller.
> + */
> + if ((udphy->mode & UDPHY_MODE_USB) && !(old_mode & UDPHY_MODE_USB) &&
> + udphy->usb_in_use && !udphy->hs)
> + return rk_udphy_power_on(udphy, UDPHY_MODE_USB);
> +
> return 0;
> }
[Severity: High]
Will this fallback logic ever execute during a replug?
When swapping a DP-only adapter for a USB-capable one, the orientation switch
callback rk_udphy_orien_sw_set() is typically invoked first. This sets the
mode to UDPHY_MODE_DP_USB.
By the time rk_udphy_typec_mux_set() is called here, udphy->mode already
includes UDPHY_MODE_USB, so old_mode will have it as well. As a result,
!(old_mode & UDPHY_MODE_USB) will evaluate to false and bypass this logic.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260625-rockchip-usbdp-cleanup-v7-0-38eb3cf654fd@collabora.com?part=24
^ permalink raw reply [flat|nested] 37+ messages in thread
* [PATCH v7 25/27] phy: rockchip: usbdp: Hold mutex in DP PHY configure
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (23 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 24/27] phy: rockchip: usbdp: Support going from DP-only mode to USB mode Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 26/27] phy: rockchip: usbdp: Add some extra debug messages Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 27/27] phy: rockchip: usbdp: Avoid xHCI SErrors Sebastian Reichel
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel, Sashiko
rk_udphy_dp_phy_configure() accesses some variables from the struct
rk_udphy, which are updated independently from the USB-C framework.
The USB-C mux/orientation switch functions already hold a mutex to
ensure mutual exclusive access to the struct rk_udphy states, so
simply hold the same one in the DP PHY configuration function.
Reproducing problems due to this on real hardware would be really hard,
but could be possible when quickly re-connecting the USB-C connector.
Fixes: 2f70bbddeb45 ("phy: rockchip: add usbdp combo phy driver")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/linux-phy/20260612164627.23D391F000E9@smtp.kernel.org/
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 182141837596..fc788f2bf5fb 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -1189,6 +1189,8 @@ static int rk_udphy_dp_phy_configure(struct phy *phy,
u32 i, val, lane;
int ret;
+ guard(mutex)(&udphy->mutex);
+
if (dp->set_rate) {
ret = rk_udphy_dp_phy_verify_link_rate(udphy, dp);
if (ret)
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 26/27] phy: rockchip: usbdp: Add some extra debug messages
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (24 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 25/27] phy: rockchip: usbdp: Hold mutex in DP PHY configure Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
2026-06-25 17:39 ` [PATCH v7 27/27] phy: rockchip: usbdp: Avoid xHCI SErrors Sebastian Reichel
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
It's useful to log PHY reinit to ease debugging issues around
USB-C hotplugging.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index fc788f2bf5fb..8c5d6b8595e2 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -24,6 +24,7 @@
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/reset.h>
+#include <linux/string_choices.h>
#include <linux/usb/ch9.h>
#include <linux/usb/typec_dp.h>
#include <linux/usb/typec_mux.h>
@@ -494,6 +495,8 @@ static void rk_udphy_u3_port_disable(struct rk_udphy *udphy, u8 disable)
const struct rk_udphy_cfg *cfg = udphy->cfgs;
const struct rk_udphy_grf_reg *preg;
+ dev_dbg(udphy->dev, "USB3 port %s\n", str_on_off(!disable));
+
preg = udphy->id ? &cfg->grfcfg.usb3otg1_cfg : &cfg->grfcfg.usb3otg0_cfg;
rk_udphy_grfreg_write(udphy->usbgrf, preg, disable);
}
@@ -787,6 +790,10 @@ static int rk_udphy_init(struct rk_udphy *udphy)
const struct rk_udphy_cfg *cfg = udphy->cfgs;
int ret;
+ dev_dbg(udphy->dev, "(re-)init PHY with USB=%s and DP=%s\n",
+ str_enabled_disabled(udphy->mode & UDPHY_MODE_USB),
+ str_enabled_disabled(udphy->mode & UDPHY_MODE_DP));
+
rk_udphy_reset_assert_all(udphy);
usleep_range(10000, 11000);
@@ -857,6 +864,8 @@ static int rk_udphy_setup(struct rk_udphy *udphy)
{
int ret;
+ dev_dbg(udphy->dev, "enable PHY\n");
+
ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks);
if (ret) {
dev_err(udphy->dev, "failed to enable clk\n");
@@ -875,6 +884,7 @@ static int rk_udphy_setup(struct rk_udphy *udphy)
static void rk_udphy_disable(struct rk_udphy *udphy)
{
+ dev_dbg(udphy->dev, "disable PHY\n");
clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks);
rk_udphy_reset_assert_all(udphy);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread* [PATCH v7 27/27] phy: rockchip: usbdp: Avoid xHCI SErrors
2026-06-25 17:39 [PATCH v7 00/27] phy: rockchip: usbdp: Fixes, DP 1-lane support and cleanups Sebastian Reichel
` (25 preceding siblings ...)
2026-06-25 17:39 ` [PATCH v7 26/27] phy: rockchip: usbdp: Add some extra debug messages Sebastian Reichel
@ 2026-06-25 17:39 ` Sebastian Reichel
26 siblings, 0 replies; 37+ messages in thread
From: Sebastian Reichel @ 2026-06-25 17:39 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, Sebastian Reichel
The USBDP PHY provides the PIPE clock to the USB3 controller, which
means the PHY must be fully running when anything tries to access
the xHCI registers.
When switching between USB3-only, USB3 + DP and DP-only mode, the
PHY must be re-initialized resulting in a short period of the PHY
being disabled. If the DWC3 driver decides to access the xHCI at
this point the system will fail with an SError.
This patch avoids the problems by disabling the USB3 port before
re-initializing it. This does a couple of things:
- forces phystatus to 0 from GRF (not from PHY)
- switches PIPE clock source from PHY to UTMI (safe fallback clock)
- num_u3_port=0
The last part will be ignored, as DWC3 already probed, but the
clock re-routing will avoid the SError. There is a small delay
afterwards to make sure the mux happened. The datasheet gives
no hints how long it takes, so delay time is a guess.
Fixes: 2f70bbddeb45 ("phy: rockchip: add usbdp combo phy driver")
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/phy/rockchip/phy-rockchip-usbdp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 8c5d6b8595e2..82ce80dc9dbc 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -1026,8 +1026,8 @@ static int rk_udphy_power_on(struct rk_udphy *udphy, u8 mode)
rk_udphy_u3_port_disable(udphy, false);
udphy->phy_needs_reinit = false;
} else if (udphy->phy_needs_reinit) {
- if (udphy->mode == UDPHY_MODE_DP)
- rk_udphy_u3_port_disable(udphy, true);
+ rk_udphy_u3_port_disable(udphy, true);
+ udelay(10);
ret = rk_udphy_init(udphy);
if (ret)
--
2.53.0
^ permalink raw reply related [flat|nested] 37+ messages in thread