* [PATCH v10 14/36] phy: rockchip: usbdp: Use FIELD_PREP_WM16_CONST
From: Sebastian Reichel @ 2026-07-03 18:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thinh Nguyen,
Greg Kroah-Hartman, Philipp Zabel
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, linux-usb, Sebastian Reichel
In-Reply-To: <20260703-rockchip-usbdp-cleanup-v10-0-a392711ca8a9@collabora.com>
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 7fb864a1486c..05593e98c16d 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
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v10 11/36] phy: rockchip: usbdp: Support single-lane DP
From: Sebastian Reichel @ 2026-07-03 18:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thinh Nguyen,
Greg Kroah-Hartman, Philipp Zabel
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, linux-usb, Sebastian Reichel
In-Reply-To: <20260703-rockchip-usbdp-cleanup-v10-0-a392711ca8a9@collabora.com>
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 7540c897dde1..c4d62b234ea8 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;
@@ -535,6 +536,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)
@@ -542,18 +550,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:
@@ -566,28 +574,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;
@@ -657,6 +643,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,
@@ -895,7 +882,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");
@@ -921,9 +908,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;
@@ -1050,18 +1039,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);
@@ -1341,6 +1329,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:
@@ -1357,6 +1346,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;
}
@@ -1501,7 +1491,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
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v10 12/36] phy: rockchip: usbdp: Limit DP lane count to muxed lanes
From: Sebastian Reichel @ 2026-07-03 18:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thinh Nguyen,
Greg Kroah-Hartman, Philipp Zabel
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, linux-usb, Sebastian Reichel, Sashiko
In-Reply-To: <20260703-rockchip-usbdp-cleanup-v10-0-a392711ca8a9@collabora.com>
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 c4d62b234ea8..b172ce6a722e 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -1099,6 +1099,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
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v10 09/36] phy: rockchip: usbdp: Fix LFPS detect threshold control
From: Sebastian Reichel @ 2026-07-03 18:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thinh Nguyen,
Greg Kroah-Hartman, Philipp Zabel
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, linux-usb, Sebastian Reichel, William Wu
In-Reply-To: <20260703-rockchip-usbdp-cleanup-v10-0-a392711ca8a9@collabora.com>
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 cb6acadfbccf..982315535caf 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
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v10 06/36] phy: rockchip: usbdp: Drop seamless DP takeover
From: Sebastian Reichel @ 2026-07-03 18:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thinh Nguyen,
Greg Kroah-Hartman, Philipp Zabel
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, linux-usb, Sebastian Reichel, Sashiko
In-Reply-To: <20260703-rockchip-usbdp-cleanup-v10-0-a392711ca8a9@collabora.com>
Right now the DRM drivers do not support seamless DP takeover and I'm
I'm not aware of any bootloader implementing this feature either.
In any case this feature would be limited to boards using the USBDP PHY
for a DP or eDP connection instead of the more commonly USB-C connector.
With USB-C's DP AltMode a seamless DP takeover requires handing over the
state of the TCPM state machine from the bootloader to the kernel. This
in turn requires a huge amount of work to keep the state machine
implementations synchronized. It's very unlikely we will see somebody
implementing that in the foreseeable future.
As the current code is obviously buggy and untested, let's simply drop
support for seamless DP takeover. It can be re-implemented cleanly once
somebody adds all missing bits.
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 | 31 -------------------------------
1 file changed, 31 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-usbdp.c b/drivers/phy/rockchip/phy-rockchip-usbdp.c
index 3fc8222fcaec..6cb9f6b4dbf6 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -452,11 +452,6 @@ static int rk_udphy_reset_assert_all(struct rk_udphy *udphy)
return reset_control_bulk_assert(udphy->num_rsts, udphy->rsts);
}
-static int rk_udphy_reset_deassert_all(struct rk_udphy *udphy)
-{
- return reset_control_bulk_deassert(udphy->num_rsts, udphy->rsts);
-}
-
static int rk_udphy_reset_deassert(struct rk_udphy *udphy, char *name)
{
struct reset_control_bulk_data *list = udphy->rsts;
@@ -924,28 +919,6 @@ static int rk_udphy_parse_lane_mux_data(struct rk_udphy *udphy)
return 0;
}
-static int rk_udphy_get_initial_status(struct rk_udphy *udphy)
-{
- int ret;
- u32 value;
-
- ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks);
- if (ret) {
- dev_err(udphy->dev, "failed to enable clk\n");
- return ret;
- }
-
- rk_udphy_reset_deassert_all(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);
-
- return 0;
-}
-
static int rk_udphy_parse_dt(struct rk_udphy *udphy)
{
struct device *dev = udphy->dev;
@@ -1495,10 +1468,6 @@ static int rk_udphy_probe(struct platform_device *pdev)
if (ret)
return ret;
- ret = rk_udphy_get_initial_status(udphy);
- if (ret)
- return ret;
-
mutex_init(&udphy->mutex);
platform_set_drvdata(pdev, udphy);
--
2.53.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v10 07/36] phy: rockchip: usbdp: Keep clocks running on PHY re-init
From: Sebastian Reichel @ 2026-07-03 18:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thinh Nguyen,
Greg Kroah-Hartman, Philipp Zabel
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, linux-usb, Sebastian Reichel
In-Reply-To: <20260703-rockchip-usbdp-cleanup-v10-0-a392711ca8a9@collabora.com>
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 6cb9f6b4dbf6..e3f5a26c876a 100644
--- a/drivers/phy/rockchip/phy-rockchip-usbdp.c
+++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c
@@ -987,8 +987,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
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v10 05/36] phy: rockchip: usbdp: Handle missing clock-names DT property gracefully
From: Sebastian Reichel @ 2026-07-03 18:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thinh Nguyen,
Greg Kroah-Hartman, Philipp Zabel
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, linux-usb, Sebastian Reichel, Sashiko
In-Reply-To: <20260703-rockchip-usbdp-cleanup-v10-0-a392711ca8a9@collabora.com>
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
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v10 08/36] phy: rockchip: usbdp: Amend SSC modulation deviation
From: Sebastian Reichel @ 2026-07-03 18:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thinh Nguyen,
Greg Kroah-Hartman, Philipp Zabel
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, linux-usb, Sebastian Reichel
In-Reply-To: <20260703-rockchip-usbdp-cleanup-v10-0-a392711ca8a9@collabora.com>
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 e3f5a26c876a..cb6acadfbccf 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
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v10 00/36] phy: rockchip: usbdp: Clean up the mess
From: Sebastian Reichel @ 2026-07-03 18:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thinh Nguyen,
Greg Kroah-Hartman, Philipp Zabel
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, linux-usb, Sebastian Reichel, Sashiko, William Wu
This series does a major overhaul of the Rockchip USBDP driver. The
initial main goal was to add USB-C DP AltMode support to the RK3576
and RK3588 and this series still prepares the PHY driver for exactly
that. But in addition to that I uncovered a huge amount of issues,
that are fixed along the way. Some of the more interesting ones are:
* Currently the driver might trigger a fatal SError on USB-C hotplug,
since re-initializing the PHY stops the clocks going to DWC3. If
the DWC3 driver tries to access its registers at the same time the
system will crash.
* The DWC3 hardware can get into a buggy state when the PHY is
disabled, which results in the PHY not coming up properly again.
* Swithcing the USB-C connector orientation during hotplug breaks
USB3 speed, as the PHY is not being re-initialized.
* The code always enables DP mode when USB-C is involved.
* The driver has some locking issues uncovered by Sashiko.
In addition to these bigger ones, Sashiko also found a bunch of
minor problems, which are mostly harmless, but were fixed while
going at it.
I've tested the v10 code changes with dozens of replugs of different
devices (2 different USB-C hubs with USB3 + HDMI via DP AltMode, 1 USB-C
to HDMI adapter [4 lanes DP AltMode], 1 USB-C to DP adapter [4 lanes DP
AltMode], 1 USB-C to NVMe adapter [no DP AltMode] as well as a direct
USB-C connection to a Dell display) on a Sige 5 board and haven't run
into any issues. In addition I also tested peripheral/gadget mode works
by plugging the USB-C port into a laptop using an USB-A to USB-C cable.
In all cases USB3 was working in both directions and DP mode was
properly initialized, so that the DRM driver could query the available
modes. Apart from that the series is boot tested via CI on Rock 5B
and Rock 4D.
Technically some of the later patches are fixes, that one would
expect at the beginning of the series, but they are only possible
after the big cleanups.
Changes in v10:
- Link to v9: https://lore.kernel.org/r/20260702-rockchip-usbdp-cleanup-v9-0-e31efbb62d2e@collabora.com
- Add 'deprecated: true' to port in DT binding, since ports replaces it (Sashiko)
- In 'Drop seamless DP takeover' simply remove any handling for
pre-enabled PHY as there is no known bootloader doing that and
Sashiko keeps finding things, which I cannot test. (Sashiko, myself)
- Use on/off instead of enabled/disabled in PHY reinit message,
which is shorter (myself)
- Use notifier_to_errno() in "add notifier infrastructure" (Sashiko)
- Rework DWC3 PHY reset notifier patch, so that it works correctly
for multiple ports (Rockchip is single-port) and keep a runtime
reference while the PHY reset is going on to massively simplify
the locking logic. (Sashiko)
- Drop patch renaming phy_needs_reinit keep the existing logic to
set it whenever the lane configuration changes (Sashiko)
- Update "Simplify power state handling" patch, to mostly depend
on the DT configured or TypeC negotiated modes to avoid
data stream disconnections when DP is hotplugged in a dock or
USB is used with runtime PM (Sashiko)
- Ensure sw_mode is not set when the PHY enablement function fails
(Sashiko)
- Add new patch adding USB-only mode as USB-C state, which results
in proper powering off the DP side when the remote hardware is
not capable of DP AltMode. (myself)
Changes in v9:
- Link to v8: https://lore.kernel.org/r/20260626-rockchip-usbdp-cleanup-v8-0-47f682987895@collabora.com
- Update DT binding to explicitly mention that port@3 is for the
DP aux channel and not DP in general (Sashiko got this wrong)
- Add a 100ms cooldown sleep in "Drop seamless DP takeover" after HPD
is force disabled (Sashiko)
- Update comment in "Register DP aux bridge" to explain why port@3 is
checked, but port@0 is used (Sashiko)
- Check for high-speed only mode in "Support going from DP-only mode to
USB mode" (Sashiko)
- Add new patch for rk_udphy_reset_deassert error handling (Sashiko)
- Add new patch to avoid enabling USB3 in high-speed only mode during
PHY reinit (Sashiko)
- Add 3 more patches to handle the LCPLL lock issue mentioned in the v8
cover letter after feedback from Rockchip. Apparently the DWC3 does
not cope very well with the PHY disappearing resulting in the PIPE
interface misbehaving, which in turn results in the LCPLL not locking.
The new patches avoid this by asserting DWC3_GUSB3PIPECTL_PHYSOFTRST.
As this assert needs to be done when the PHY wants to reset, a new
notifier system has been implemented to support triggering this from
the PHY driver. This also means, that this version now also involves
the USB subsystem.
- Drop old patch trying to solve the DP-only -> USB mode switch in
favour of 5 new patches completely rewriting and simplifying the
power status handling. The new code ensures that the PHY always
has the right modes enabled and also makes sure a re-init happens
on an orientation change.
- rebased on v7.2-rc1
Changes in v8:
- Link to v7: https://lore.kernel.org/r/20260625-rockchip-usbdp-cleanup-v7-0-38eb3cf654fd@collabora.com
- Move patch "Limit DP lane count to muxed lanes" after single lane
support, which introduces dp_lanes variable to make sure series
is bi-sectable (Sashiko)
- Force disable HPD in "Drop seamless DP takeover" patch and update
patch description to mention potential issues with SErrors for
bootloaders really keeping the DW-DP on. As mentioned in the new
commit message this is untested as I'm not aware of such a
bootloader anyways; this also means we need to keep the HPD GRF
register defines in the 'Drop DP HPD handling' patch (Sashiko)
- Fix mode logic in "Properly handle TYPEC_STATE_SAFE and
TYPEC_STATE_USB" patch; I blame the heat (Sashiko)
- Improve "Support going from DP-only mode to USB mode" patch to
better handle starting in DP only mode; due to TypeC logic
starting delayed this does not really happen, though (Sashiko)
- Improve "Support going from DP-only mode to USB mode" to avoid
checking previous state and instead power on USB state based
on previous requested state to avoid effects from the flip
callback (Sashiko)
- Update the debug message patch to include some more info
- Ad one more patch, which disables USB3 at startup and drops
the -EPROBE_DEFER logic
Changes in v7:
- Link to v6: https://lore.kernel.org/r/20260619-rockchip-usbdp-cleanup-v6-0-3bb1f54b3f35@collabora.com
- Add new patch handling missing clock-names in DT gracefully (Sashiko)
- Add new patch handling rk_udphy_reset_deassert_all errors in init check (Sashiko)
- Add new patch to handle Properly handle TYPEC_STATE_SAFE and TYPEC_STATE_USB (Sashiko)
- Add new patch to avoid xHCI SErrors
Changes in v6:
- Link to v5: https://lore.kernel.org/r/20260612-rockchip-usbdp-cleanup-v5-0-efc83069869f@collabora.com
- Add explicit <linux/string_choices.h> include in last patch (Sashiko)
- Add new patch moving mode_change update after error handling (Sashiko)
- Add new patch fixing error masking of devm_clk_bulk_get_all() (Sashiko)
- Add new patch dropping seamless DP takeover as it is non-functional and buggy (Sashiko)
- Add new patch limiting DP lane count to muxed lanes (Sashiko)
- Add error handling in the patch that keeps clocks running on PHY re-init (Sashiko)
- Also look for DP being configured to second lane for the flip config
in DP single-lane mode, which should at least keep USB working for
this super unusual config (Sashiko)
- Drop useless ret variable in patch introducing guard() for the mutex
- Add error handling for PHY re-enablement in the patch fixing support for
DP-only -> USB mode (Sashiko)
Changes in v5:
- Link to v4: https://lore.kernel.org/r/20260428-rockchip-usbdp-cleanup-v4-0-7775671ece22@collabora.com
- Picked up Acked-by from Rob Herring for DT binding
- Fix typos in commit messages/comments
- Add Fixes tag to "Do not looe USB3 PHY status" patch
- Collect Reviewed-by: Neil Armstrong for multiple patches
- Drop now unused code from "Drop DP HPD handling" patch (Sashiko)
- Ignore mux events not involving DP AltMode (Sashiko)
- Add new patch to support going back from DP only mode to USB combo
mode; technically this is a fix, but DP mode does not yet work
upstream, so it does not matter (Sashiko)
- Add new patch adding a few debug messages, which are useful
to investigate potential hotplug issues in the future
- Sashiko comments about the DT binding and property usage
are wrong as the first port is for the superspeed lanes
used for DP and USB, while the last port is just about
DP aux. I ignored them.
- There is a pre-existing bug, that can already be hit with the
upstream kernel and that the series doesn't fix properly:
Accessing the USB3 controller registers requires the USB PHY
running, since it provides a clock. Re-initializing the PHY
means there is a race-condition - if the system tries to access
the USB3 controller in parallel to the re-init, the system will
hang and/or fail with an SError. By keeping the clocks running
and only asserting the resets this time is minimized by this
series. A proper fix for this will be looked into independently
from this series.
- I used v7.1-rc6 as base, but the driver has no changes since
6.18 even in linux-next and there are no pending patches for
it on the mailinglist either, so it applies to *any* recent
kernel branch.
Changes in v4:
- Link to v3: https://lore.kernel.org/r/20260313-rockchip-usbdp-cleanup-v3-0-3e8fe89a35b5@collabora.com
- rebased to v7.1-rc1 (no changes)
- Update DRM bridge registration patch to avoid registration when DP aux
port is not connected to anything, since this results in errors and some
boards use USBDP instances for USB3 only.
- Add patch renaming mode_change into phy_needs_reinit
- Add patch to re-init PHY on orientation change
- Add patch to factor out lane_mux_sel setup
- Add patch to handle mutex via guard functions
Changes in v3:
- Link to v2: https://lore.kernel.org/r/20260213-rockchip-usbdp-cleanup-v2-0-b67ec225f96e@collabora.com
- Add patch to register the USBDP PHY as DRM bridge
- Add patch to describe ports in DT binding (used by the DRM bridge)
- Add patch to drop HPD handling from the PHY
Changes in v2:
- Link to v1: https://lore.kernel.org/r/20260203-rockchip-usbdp-cleanup-v1-0-16a6f92ed176@collabora.com
- Added new patches to fix USB3 SError
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
Frank Wang (1):
phy: rockchip: usbdp: Amend SSC modulation deviation
Sebastian Reichel (33):
dt-bindings: phy: rockchip-usbdp: add improved ports scheme
phy: rockchip: usbdp: Update mode_change after error handling
phy: rockchip: usbdp: Do not lose USB3 PHY status
phy: rockchip: usbdp: Fix devm_clk_bulk_get_all check
phy: rockchip: usbdp: Handle missing clock-names DT property gracefully
phy: rockchip: usbdp: Drop seamless DP takeover
phy: rockchip: usbdp: Keep clocks running on PHY re-init
phy: rockchip: usbdp: Add missing mode_change update
phy: rockchip: usbdp: Limit DP lane count to muxed lanes
phy: rockchip: usbdp: Rename DP lane functions
phy: rockchip: usbdp: Use FIELD_PREP_WM16_CONST
phy: rockchip: usbdp: Cleanup DP lane selection function
phy: rockchip: usbdp: Register DP aux bridge
phy: rockchip: usbdp: Drop DP HPD handling
phy: rockchip: usbdp: Rename mode_change to phy_needs_reinit
phy: rockchip: usbdp: Re-init the PHY on orientation change
phy: rockchip: usbdp: Factor out lane_mux_sel setup
phy: rockchip: usbdp: Properly handle TYPEC_STATE_SAFE and TYPEC_STATE_USB
phy: rockchip: usbdp: Use guard functions for mutex
phy: rockchip: usbdp: Clear USB status on PHY exit
phy: rockchip: usbdp: Hold mutex in DP PHY configure
phy: rockchip: usbdp: Add some extra debug messages
phy: rockchip: usbdp: Avoid xHCI SErrors
phy: rockchip: usbdp: Handle rk_udphy_reset_deassert errors
phy: rockchip: usbdp: Only enable USB3 when not in high-speed mode
phy: core: add notifier infrastructure
usb: dwc3: core: support PHY reset notifications
phy: rockchip: usbdp: Add phy reset notification support
phy: rockchip: usbdp: Drop -EPROBE_DEFER hack
phy: rockchip: usbdp: Rename mode to hw_mode
phy: rockchip: usbdp: Simplify power state handling
phy: rockchip: usbdp: Re-init PHY on mux change
phy: rockchip: usbdp: Add USB-C state without DP enabled
William Wu (1):
phy: rockchip: usbdp: Fix LFPS detect threshold control
Zhang Yubing (1):
phy: rockchip: usbdp: Support single-lane DP
.../bindings/phy/phy-rockchip-usbdp.yaml | 24 +
drivers/phy/phy-core.c | 60 +++
drivers/phy/rockchip/Kconfig | 2 +
drivers/phy/rockchip/phy-rockchip-usbdp.c | 584 ++++++++++-----------
drivers/usb/dwc3/core.c | 74 +++
drivers/usb/dwc3/core.h | 16 +
include/linux/phy/phy.h | 40 ++
7 files changed, 501 insertions(+), 299 deletions(-)
---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20260203-rockchip-usbdp-cleanup-5b59dfb561a3
Best regards,
--
Sebastian Reichel <sebastian.reichel@collabora.com>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH v10 01/36] dt-bindings: phy: rockchip-usbdp: add improved ports scheme
From: Sebastian Reichel @ 2026-07-03 18:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thinh Nguyen,
Greg Kroah-Hartman, Philipp Zabel
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, linux-usb, Sebastian Reichel
In-Reply-To: <20260703-rockchip-usbdp-cleanup-v10-0-a392711ca8a9@collabora.com>
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 | 24 ++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml b/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
index 8b7059d5b182..35d6717b9cc9 100644
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-usbdp.yaml
@@ -110,10 +110,34 @@ properties:
port:
$ref: /schemas/graph.yaml#/properties/port
+ depreated: true
description:
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 Auxiliary, 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
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v10 02/36] phy: rockchip: usbdp: Update mode_change after error handling
From: Sebastian Reichel @ 2026-07-03 18:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thinh Nguyen,
Greg Kroah-Hartman, Philipp Zabel
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, linux-usb, Sebastian Reichel, Sashiko
In-Reply-To: <20260703-rockchip-usbdp-cleanup-v10-0-a392711ca8a9@collabora.com>
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
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v10 03/36] phy: rockchip: usbdp: Do not lose USB3 PHY status
From: Sebastian Reichel @ 2026-07-03 18:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thinh Nguyen,
Greg Kroah-Hartman, Philipp Zabel
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, linux-usb, Sebastian Reichel
In-Reply-To: <20260703-rockchip-usbdp-cleanup-v10-0-a392711ca8a9@collabora.com>
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
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v10 04/36] phy: rockchip: usbdp: Fix devm_clk_bulk_get_all check
From: Sebastian Reichel @ 2026-07-03 18:13 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Heiko Stuebner, Frank Wang,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Thinh Nguyen,
Greg Kroah-Hartman, Philipp Zabel
Cc: Andy Yan, Dmitry Baryshkov, Yubing Zhang, Alexey Charkov,
linux-phy, linux-arm-kernel, linux-rockchip, linux-kernel, kernel,
devicetree, linux-usb, Sebastian Reichel, Sashiko
In-Reply-To: <20260703-rockchip-usbdp-cleanup-v10-0-a392711ca8a9@collabora.com>
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
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* Re: [PATCH v2 2/2] phy: spacemit: Add USB3/PCIe comb PHY driver for Spacemit K3
From: Aurelien Jarno @ 2026-07-03 17:12 UTC (permalink / raw)
To: Inochi Amaoto
Cc: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yixun Lan, Kees Cook, Gustavo A. R. Silva,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Alex Elder, Ze Huang, linux-phy, devicetree, linux-riscv,
spacemit, linux-kernel, linux-hardening, Yixun Lan, Longbin Li
In-Reply-To: <20260703021024.495433-3-inochiama@gmail.com>
On 2026-07-03 10:10, Inochi Amaoto wrote:
> The comb PHY on K3 requires to configure a syscon device for the
> right mux configuration. And it requires calibration before any
> usage.
>
> Add USB3/PCIe comb PHY driver for Spacemit K3.
>
> Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
> ---
> drivers/phy/spacemit/Kconfig | 16 ++
> drivers/phy/spacemit/Makefile | 2 +
> drivers/phy/spacemit/phy-k3-combo.c | 252 +++++++++++++++++
> drivers/phy/spacemit/phy-k3-common.c | 391 +++++++++++++++++++++++++++
> drivers/phy/spacemit/phy-k3-common.h | 27 ++
> 5 files changed, 688 insertions(+)
> create mode 100644 drivers/phy/spacemit/phy-k3-combo.c
> create mode 100644 drivers/phy/spacemit/phy-k3-common.c
> create mode 100644 drivers/phy/spacemit/phy-k3-common.h
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
--
Aurelien Jarno GPG: 4096R/1DDD8C9B
aurelien@aurel32.net http://aurel32.net
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH 3/4] arm64: dts: qcom: Add Shikra CQM SoM platform
From: Dmitry Baryshkov @ 2026-07-03 15:32 UTC (permalink / raw)
To: Rakesh Kota
Cc: Konrad Dybcio, Kamal Wadhwa, linux-arm-msm, sashiko-reviews,
Komal Bajaj, robh, linux-phy, neil.armstrong, vkoul, olteanv,
krzk+dt, conor+dt, devicetree, Jishnu Prakash
In-Reply-To: <20260703093035.q5xgljuigpt6zqt6@hu-kotarake-hyd.qualcomm.com>
On Fri, Jul 03, 2026 at 03:00:35PM +0530, Rakesh Kota wrote:
> On Tue, Jun 30, 2026 at 03:50:16PM +0200, Konrad Dybcio wrote:
> > On 6/30/26 2:42 PM, Rakesh Kota wrote:
> > > On Sun, Jun 28, 2026 at 03:33:23PM +0300, Dmitry Baryshkov wrote:
> > >> On Thu, Jun 25, 2026 at 09:11:19PM +0530, Kamal Wadhwa wrote:
> > >>> On Wed, Jun 17, 2026 at 03:48:14PM +0300, Dmitry Baryshkov wrote:
> > >>>> On Mon, 18 May 2026 at 14:49, Kamal Wadhwa
> > >>>> <kamal.wadhwa@oss.qualcomm.com> wrote:
> > >>>>>
> > >>>>> On Sun, May 17, 2026 at 08:18:15PM +0300, Dmitry Baryshkov wrote:
> > >>>>>> On Thu, May 14, 2026 at 04:09:18PM +0530, Kamal Wadhwa wrote:
> > >>>>>>> On Wed, May 13, 2026 at 06:14:20PM +0300, Dmitry Baryshkov wrote:
> > >>>>>>>> On 13/05/2026 17:29, Rakesh Kota wrote:
> > >>>>>>>>> On Wed, May 13, 2026 at 03:01:47PM +0300, Dmitry Baryshkov wrote:
> > >>>>>>>>>> On Wed, May 13, 2026 at 04:28:35AM +0000, sashiko-bot@kernel.org wrote:
> > >>>>>>>>>>> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> > >>>>>>>>>>> - [High] The PMIC regulator definitions omit their required input supply dependencies (e.g., `vdd_s2-supply`, `vdd_l3-supply`), breaking the power hierarchy.
> > >>>>>>>>>>> - [Medium] The device tree inaccurately hardcodes the `compatible` string to a different PMIC model (`qcom,rpm-pm2250-regulators`) instead of explicitly identifying the actual hardware (PM4125).
> > >>>>>>>>>>> --
> > >>>>>>>>>>>> +
> > >>>>>>>>>>>> + pm4125_s2: s2 {
> > >>>>>>>>>>>> + regulator-min-microvolt = <1000000>;
> > >>>>>>>>>>>> + regulator-max-microvolt = <1200000>;
> > >>>>>>>>>>>> + };
> > >>>>>>>>>>>
> > >>>>>>>>>>> Do these regulators need to explicitly define their input supply dependencies
> > >>>>>>>>>>> such as vdd_s2-supply?
> > >>>>>>>>>>>
> > >>>>>>>>>>> Without these properties, the regulator framework might be unaware that the
> > >>>>>>>>>>> PMIC regulators draw power from upstream supplies.
> > >>>>>>>>>>>
> > >>>>>>>>>>> If the kernel dynamically manages the upstream supply and its reference count
> > >>>>>>>>>>> drops to zero, could it be disabled, causing an unexpected power loss for
> > >>>>>>>>>>> downstream components?
> > >>>>>>>>>>
> > >>>>>>>>>> And this is a correct comment. Please provide missing supplies.
> > >>>>>>>>>>
> > >>>>>>>>> As per the Qualcomm system design, the parent-child supply relationship
> > >>>>>>>>> is managed by the RPM firmware, not the Linux regulator framework. The
> > >>>>>>>>> RPM ensures the parent supply is never disabled until all subsystem
> > >>>>>>>>> votes are cleared.
> > >>>>>>>>
> > >>>>>>>> How is this different from other, previous platforms?
> > >>>>>>>
> > >>>>>>> This is not different. In the previous platforms too this is taken care from the
> > >>>>>>> RPM/RPMH firmware side, the only case where we may need explicit vote to parent
> > >>>>>>> is for non-rpmh/rpm regulator rails (like i2c based regulator pm8008), which
> > >>>>>>> may have a RPM/RPMH regulator as a parent.
> > >>>>>>>
> > >>>>>>> Even on those previous targets the parent rail of all RPM/RPMH regulators are
> > >>>>>>> internally voted by RPM/RPMH FW at proper voltage with required headroom
> > >>>>>>> calculated based on the active child rails. This was done for all the
> > >>>>>>> subsystems (including APPS) regulators.
> > >>>>>>>
> > >>>>>>> So no explicit handling from the APPS is required for parent supply.
> > >>>>>>
> > >>>>>> You are explaining the driver behaviour. But the question is about the
> > >>>>>> hardware description. If there is no difference, please add necessary
> > >>>>>> supplies back.
> > >>>>>
> > >>>>> I understand your concern about descibing the parent-child relation in the
> > >>>>> devicetree, and given that we have been almost always followed this for all
> > >>>>> the previous targets, it will expected of us to add them.
> > >>>>
> > >>>> Yes.
> > >>>>
> > >>>>>
> > >>>>> However, we want to avoid the unnecessary access to the parent from APPS.
> > >>>>
> > >>>> Why? What is the reason? Do we want to do the same for all the
> > >>>> platforms? Only for Shikra? Something else?
> > >>>>
> > >>>>> At the moment, I do not see a way to avoid that, if we add the parent
> > >>>>> regulators.
> > >>>>
> > >>>> That depend on the answer to the previous question. In the end, we can
> > >>>> make the driver ignore the parents by removing them from the regulator
> > >>>> desc.
> > >>>
> > >>> Ok, this seems like a good suggestion, so you mean its ok if we define the
> > >>> regulator desc's supply column with NULL? And only keep that in the DT?
> > >>>
> > >>> you mean like this?
> > >>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/regulator/qcom-rpmh-regulator.c?h=v7.1#n1453
> > >>>
> > >>> (please let me know if i got that right. thanks)
> > >>
> > >> Yes. Don't forget to explain in the commit message, why you are doing
> > >> so.
> > >
> > > Currently, Agatti uses the same PMIC, so we cannot set the driver
> > > supply name reference to NULL. Since it's an older target,
> > > we'll need to run a regression before making any driver-level changes.
> > >
> > > Additionally, the child-to-parent regulator ganging differs between
> > > Shikra and Agatti:
> > >
> > > - On Agatti, l3 regulator is ganged with vdd_l13_l14_l15_l16
> > > - On Shikra, l3 is ganged with vdd_l2_l3
> >
> > Is it configurable on the PMIC level? I was under the impression the
> > supply maps are fixed in hardware. Is there a chance the agatti
> > description is just wrong?
>
> The supply ganging between child LDOs and parent supplies is not fixed
> at the PMIC hardware level — it varies per platform based on system
> design requirements. The same LDO can have a different parent supply on
> different SoCs.
It can have different power supplies, but the supply is provided through
a fixed pin of the PMIC. Please correct me if I'm wrong.
> I have verified the Agatti parent-child supply mappings and they are
> correct. The difference between Agatti and Shikra is a legitimate
> platform-level design difference, not an error in the Agatti DT.
There is an error in the DT. It uses fake PMIC supply names.
--
With best wishes
Dmitry
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH 3/4] arm64: dts: qcom: Add Shikra CQM SoM platform
From: Dmitry Baryshkov @ 2026-07-03 15:28 UTC (permalink / raw)
To: Rakesh Kota
Cc: Kamal Wadhwa, linux-arm-msm, sashiko-reviews, Komal Bajaj, robh,
linux-phy, neil.armstrong, vkoul, olteanv, krzk+dt, conor+dt,
devicetree, Jishnu Prakash
In-Reply-To: <20260630124220.4lja4zshpf66kwj3@hu-kotarake-hyd.qualcomm.com>
On Tue, Jun 30, 2026 at 06:12:20PM +0530, Rakesh Kota wrote:
> On Sun, Jun 28, 2026 at 03:33:23PM +0300, Dmitry Baryshkov wrote:
> > On Thu, Jun 25, 2026 at 09:11:19PM +0530, Kamal Wadhwa wrote:
> > > On Wed, Jun 17, 2026 at 03:48:14PM +0300, Dmitry Baryshkov wrote:
> > > > On Mon, 18 May 2026 at 14:49, Kamal Wadhwa
> > > > <kamal.wadhwa@oss.qualcomm.com> wrote:
> > > > >
> > > > > On Sun, May 17, 2026 at 08:18:15PM +0300, Dmitry Baryshkov wrote:
> > > > > > On Thu, May 14, 2026 at 04:09:18PM +0530, Kamal Wadhwa wrote:
> > > > > > > On Wed, May 13, 2026 at 06:14:20PM +0300, Dmitry Baryshkov wrote:
> > > > > > > > On 13/05/2026 17:29, Rakesh Kota wrote:
> > > > > > > > > On Wed, May 13, 2026 at 03:01:47PM +0300, Dmitry Baryshkov wrote:
> > > > > > > > > > On Wed, May 13, 2026 at 04:28:35AM +0000, sashiko-bot@kernel.org wrote:
> > > > > > > > > > > Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> > > > > > > > > > > - [High] The PMIC regulator definitions omit their required input supply dependencies (e.g., `vdd_s2-supply`, `vdd_l3-supply`), breaking the power hierarchy.
> > > > > > > > > > > - [Medium] The device tree inaccurately hardcodes the `compatible` string to a different PMIC model (`qcom,rpm-pm2250-regulators`) instead of explicitly identifying the actual hardware (PM4125).
> > > > > > > > > > > --
> > > > > > > > > > > > +
> > > > > > > > > > > > + pm4125_s2: s2 {
> > > > > > > > > > > > + regulator-min-microvolt = <1000000>;
> > > > > > > > > > > > + regulator-max-microvolt = <1200000>;
> > > > > > > > > > > > + };
> > > > > > > > > > >
> > > > > > > > > > > Do these regulators need to explicitly define their input supply dependencies
> > > > > > > > > > > such as vdd_s2-supply?
> > > > > > > > > > >
> > > > > > > > > > > Without these properties, the regulator framework might be unaware that the
> > > > > > > > > > > PMIC regulators draw power from upstream supplies.
> > > > > > > > > > >
> > > > > > > > > > > If the kernel dynamically manages the upstream supply and its reference count
> > > > > > > > > > > drops to zero, could it be disabled, causing an unexpected power loss for
> > > > > > > > > > > downstream components?
> > > > > > > > > >
> > > > > > > > > > And this is a correct comment. Please provide missing supplies.
> > > > > > > > > >
> > > > > > > > > As per the Qualcomm system design, the parent-child supply relationship
> > > > > > > > > is managed by the RPM firmware, not the Linux regulator framework. The
> > > > > > > > > RPM ensures the parent supply is never disabled until all subsystem
> > > > > > > > > votes are cleared.
> > > > > > > >
> > > > > > > > How is this different from other, previous platforms?
> > > > > > >
> > > > > > > This is not different. In the previous platforms too this is taken care from the
> > > > > > > RPM/RPMH firmware side, the only case where we may need explicit vote to parent
> > > > > > > is for non-rpmh/rpm regulator rails (like i2c based regulator pm8008), which
> > > > > > > may have a RPM/RPMH regulator as a parent.
> > > > > > >
> > > > > > > Even on those previous targets the parent rail of all RPM/RPMH regulators are
> > > > > > > internally voted by RPM/RPMH FW at proper voltage with required headroom
> > > > > > > calculated based on the active child rails. This was done for all the
> > > > > > > subsystems (including APPS) regulators.
> > > > > > >
> > > > > > > So no explicit handling from the APPS is required for parent supply.
> > > > > >
> > > > > > You are explaining the driver behaviour. But the question is about the
> > > > > > hardware description. If there is no difference, please add necessary
> > > > > > supplies back.
> > > > >
> > > > > I understand your concern about descibing the parent-child relation in the
> > > > > devicetree, and given that we have been almost always followed this for all
> > > > > the previous targets, it will expected of us to add them.
> > > >
> > > > Yes.
> > > >
> > > > >
> > > > > However, we want to avoid the unnecessary access to the parent from APPS.
> > > >
> > > > Why? What is the reason? Do we want to do the same for all the
> > > > platforms? Only for Shikra? Something else?
> > > >
> > > > > At the moment, I do not see a way to avoid that, if we add the parent
> > > > > regulators.
> > > >
> > > > That depend on the answer to the previous question. In the end, we can
> > > > make the driver ignore the parents by removing them from the regulator
> > > > desc.
> > >
> > > Ok, this seems like a good suggestion, so you mean its ok if we define the
> > > regulator desc's supply column with NULL? And only keep that in the DT?
> > >
> > > you mean like this?
> > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/regulator/qcom-rpmh-regulator.c?h=v7.1#n1453
> > >
> > > (please let me know if i got that right. thanks)
> >
> > Yes. Don't forget to explain in the commit message, why you are doing
> > so.
>
> Currently, Agatti uses the same PMIC, so we cannot set the driver
> supply name reference to NULL. Since it's an older target,
> we'll need to run a regression before making any driver-level changes.
Sure, just do it please.
> Additionally, the child-to-parent regulator ganging differs between
> Shikra and Agatti:
>
> - On Agatti, l3 regulator is ganged with vdd_l13_l14_l15_l16
> - On Shikra, l3 is ganged with vdd_l2_l3
Well, somebody tried to be too smart when contributing Agatti. Now that
needs to be fixed. Be sure to keep backwards compatibility with the
existing DTs.
From the schematics that I see, the pins are:
- vin_l1
- vin_l2_l3
- vin_l5_l6_l7_l11_l12
- vin_l8_l9
- vin_l10
- vin_l13_l14
- vin_l15_l16
- vin_l17_l22
- vin_l18_l19
- vin_l4_l20_l21
- vin_xo_rf
Please correct the bindings and adjust the driver.
> Since vdd_l2_l3 is not present as a supply name in the driver, it will
> be skipped by the driver and would only serve as a representational
> reference in the DT.
>
> We have two options to consider:
>
> Option 1: Skip adding the child/parent relationship for Shikra for now,
> since the DT bindings are not enforcing it. (Ref:
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml?h=v7.1)
>
> Option 2: Go ahead and add the Shikra-specific ganging in DT now. Since
> the supply name (vdd_l2_l3) does not match what the driver expects
> (Agatti's mapping), it will be gracefully skipped by the driver — making
> it safe to add for documentation/representation purposes without any
> functional impact.
>
> So,Please share your thoughts on above options ?
Option 3. The PMIC is not Shikra-specific. You've spotted an error.
Correct the way it is described an used while adding support for Shikra.
--
With best wishes
Dmitry
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH 2/2] dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Add Maili PCIe PHY compatibles
From: Vivek Pernamitta @ 2026-07-03 12:08 UTC (permalink / raw)
To: Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Vinod Koul,
Neil Armstrong
Cc: linux-arm-msm, linux-pci, devicetree, linux-kernel, linux-phy,
Vivek Pernamitta
In-Reply-To: <20260703-vdev_maili_dt_bindings-v1-0-c9df0916cd5e@oss.qualcomm.com>
Add qcom,maili-qmp-gen3x2-pcie-phy and qcom,maili-qmp-gen4x1-pcie-phy
compatible strings for the Maili SoC PCIe QMP PHY.
The Maili SoC is a derivative of Hawi and shares the same PCIe QMP PHY
architecture, allowing reuse of the existing Hawi PCIe PHY DT bindings.
Signed-off-by: Vivek Pernamitta <vivek.pernamitta@oss.qualcomm.com>
---
Dependencies:
- phy: qcom: qmp-pcie: Add PCIe PHY support for Hawi
https://lore.kernel.org/all/20260618-hawi-phy-pcie-v3-0-3fa42ca45ea4@oss.qualcomm.com/
---
.../devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
index 259ed9678393f12c03535389b972fed0c7e36517..971474526cf97cf333a80a31e8fb13abcb995e97 100644
--- a/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml
@@ -23,6 +23,8 @@ properties:
- qcom,hawi-qmp-gen3x2-pcie-phy
- qcom,hawi-qmp-gen4x1-pcie-phy
- qcom,kaanapali-qmp-gen3x2-pcie-phy
+ - qcom,maili-qmp-gen3x2-pcie-phy
+ - qcom,maili-qmp-gen4x1-pcie-phy
- qcom,qcs615-qmp-gen3x1-pcie-phy
- qcom,qcs8300-qmp-gen4x2-pcie-phy
- qcom,sa8775p-qmp-gen4x2-pcie-phy
@@ -200,6 +202,8 @@ allOf:
- qcom,glymur-qmp-gen5x4-pcie-phy
- qcom,hawi-qmp-gen3x2-pcie-phy
- qcom,hawi-qmp-gen4x1-pcie-phy
+ - qcom,maili-qmp-gen3x2-pcie-phy
+ - qcom,maili-qmp-gen4x1-pcie-phy
- qcom,qcs8300-qmp-gen4x2-pcie-phy
- qcom,sa8775p-qmp-gen4x2-pcie-phy
- qcom,sa8775p-qmp-gen4x4-pcie-phy
@@ -230,6 +234,8 @@ allOf:
- qcom,hawi-qmp-gen3x2-pcie-phy
- qcom,hawi-qmp-gen4x1-pcie-phy
- qcom,kaanapali-qmp-gen3x2-pcie-phy
+ - qcom,maili-qmp-gen3x2-pcie-phy
+ - qcom,maili-qmp-gen4x1-pcie-phy
- qcom,sm8550-qmp-gen4x2-pcie-phy
- qcom,sm8650-qmp-gen4x2-pcie-phy
- qcom,x1e80100-qmp-gen3x2-pcie-phy
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 1/2] dt-bindings: pci: qcom,hawi-pcie: Add Maili PCIe compatible
From: Vivek Pernamitta @ 2026-07-03 12:08 UTC (permalink / raw)
To: Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Vinod Koul,
Neil Armstrong
Cc: linux-arm-msm, linux-pci, devicetree, linux-kernel, linux-phy,
Vivek Pernamitta
In-Reply-To: <20260703-vdev_maili_dt_bindings-v1-0-c9df0916cd5e@oss.qualcomm.com>
Add qcom,maili-pcie as a compatible string that falls back to
qcom,hawi-pcie, as the Maili SoC reuses the Hawi PCIe controller IP.
The Maili SoC is a derivative of Hawi and shares the same PCIe
controller architecture, allowing reuse of the existing Hawi PCIe
DT bindings.
Signed-off-by: Vivek Pernamitta <vivek.pernamitta@oss.qualcomm.com>
---
Dependencies:
- PCI: qcom: Add PCIe support for upcoming Hawi SoC
https://lore.kernel.org/all/20260625-hawi-pcie-v4-0-1a578603cd86@oss.qualcomm.com/
---
Documentation/devicetree/bindings/pci/qcom,hawi-pcie.yaml | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/pci/qcom,hawi-pcie.yaml b/Documentation/devicetree/bindings/pci/qcom,hawi-pcie.yaml
index 2c999ca6b2052760a192e9c464d86b73e86d3a88..aba89b59915528ef112e74982bfffc79ad6f93e0 100644
--- a/Documentation/devicetree/bindings/pci/qcom,hawi-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/qcom,hawi-pcie.yaml
@@ -16,7 +16,12 @@ description:
properties:
compatible:
- const: qcom,hawi-pcie
+ oneOf:
+ - const: qcom,hawi-pcie
+ - items:
+ - enum:
+ - qcom,maili-pcie
+ - const: qcom,hawi-pcie
reg:
items:
--
2.34.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH 0/2] dt-bindings: pci: qcom,hawi-pcie: Add Maili PCIe compatibles
From: Vivek Pernamitta @ 2026-07-03 12:08 UTC (permalink / raw)
To: Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Vinod Koul,
Neil Armstrong
Cc: linux-arm-msm, linux-pci, devicetree, linux-kernel, linux-phy,
Vivek Pernamitta
Add the qcom,maili-pcie compatible string and make it fall back to
qcom,hawi-pcie, as the Maili SoC reuses the Hawi PCIe controller IP.
Also add the qcom,maili-qmp-gen3x2-pcie-phy and
qcom,maili-qmp-gen4x1-pcie-phy compatible strings for the PCIe QMP PHYs
used on the Maili SoC.
The Maili SoC is a derivative of Hawi and shares the same PCIe
controller and PHY architecture, allowing reuse of the existing Hawi
PCIe DT bindings.
Dependencies:
- PCI: qcom: Add PCIe support for upcoming Hawi SoC
https://lore.kernel.org/all/20260625-hawi-pcie-v4-0-1a578603cd86@oss.qualcomm.com/
- phy: qcom: qmp-pcie: Add PCIe PHY support for Hawi
https://lore.kernel.org/all/20260618-hawi-phy-pcie-v3-0-3fa42ca45ea4@oss.qualcomm.com/
Signed-off-by: Vivek Pernamitta <vivek.pernamitta@oss.qualcomm.com>
---
Vivek Pernamitta (2):
dt-bindings: pci: qcom,hawi-pcie: Add Maili PCIe compatible
dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Add Maili PCIe PHY compatibles
Documentation/devicetree/bindings/pci/qcom,hawi-pcie.yaml | 7 ++++++-
.../devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml | 6 ++++++
2 files changed, 12 insertions(+), 1 deletion(-)
---
base-commit: ac5f929f2f373245abe6fac242c8d3fec4ca38af
change-id: 20260702-vdev_maili_dt_bindings-80e0730f8390
prerequisite-change-id: 20260702-vdev_hawi_changes-275c59f70bfb:v1
Best regards,
--
Vivek Pernamitta <vivek.pernamitta@oss.qualcomm.com>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH 3/4] arm64: dts: qcom: Add Shikra CQM SoM platform
From: Rakesh Kota @ 2026-07-03 9:30 UTC (permalink / raw)
To: Konrad Dybcio
Cc: Dmitry Baryshkov, Kamal Wadhwa, linux-arm-msm, sashiko-reviews,
Komal Bajaj, robh, linux-phy, neil.armstrong, vkoul, olteanv,
krzk+dt, conor+dt, devicetree, Jishnu Prakash
In-Reply-To: <33c74e59-076a-4877-9e62-83a8ebbf2d54@oss.qualcomm.com>
On Tue, Jun 30, 2026 at 03:50:16PM +0200, Konrad Dybcio wrote:
> On 6/30/26 2:42 PM, Rakesh Kota wrote:
> > On Sun, Jun 28, 2026 at 03:33:23PM +0300, Dmitry Baryshkov wrote:
> >> On Thu, Jun 25, 2026 at 09:11:19PM +0530, Kamal Wadhwa wrote:
> >>> On Wed, Jun 17, 2026 at 03:48:14PM +0300, Dmitry Baryshkov wrote:
> >>>> On Mon, 18 May 2026 at 14:49, Kamal Wadhwa
> >>>> <kamal.wadhwa@oss.qualcomm.com> wrote:
> >>>>>
> >>>>> On Sun, May 17, 2026 at 08:18:15PM +0300, Dmitry Baryshkov wrote:
> >>>>>> On Thu, May 14, 2026 at 04:09:18PM +0530, Kamal Wadhwa wrote:
> >>>>>>> On Wed, May 13, 2026 at 06:14:20PM +0300, Dmitry Baryshkov wrote:
> >>>>>>>> On 13/05/2026 17:29, Rakesh Kota wrote:
> >>>>>>>>> On Wed, May 13, 2026 at 03:01:47PM +0300, Dmitry Baryshkov wrote:
> >>>>>>>>>> On Wed, May 13, 2026 at 04:28:35AM +0000, sashiko-bot@kernel.org wrote:
> >>>>>>>>>>> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> >>>>>>>>>>> - [High] The PMIC regulator definitions omit their required input supply dependencies (e.g., `vdd_s2-supply`, `vdd_l3-supply`), breaking the power hierarchy.
> >>>>>>>>>>> - [Medium] The device tree inaccurately hardcodes the `compatible` string to a different PMIC model (`qcom,rpm-pm2250-regulators`) instead of explicitly identifying the actual hardware (PM4125).
> >>>>>>>>>>> --
> >>>>>>>>>>>> +
> >>>>>>>>>>>> + pm4125_s2: s2 {
> >>>>>>>>>>>> + regulator-min-microvolt = <1000000>;
> >>>>>>>>>>>> + regulator-max-microvolt = <1200000>;
> >>>>>>>>>>>> + };
> >>>>>>>>>>>
> >>>>>>>>>>> Do these regulators need to explicitly define their input supply dependencies
> >>>>>>>>>>> such as vdd_s2-supply?
> >>>>>>>>>>>
> >>>>>>>>>>> Without these properties, the regulator framework might be unaware that the
> >>>>>>>>>>> PMIC regulators draw power from upstream supplies.
> >>>>>>>>>>>
> >>>>>>>>>>> If the kernel dynamically manages the upstream supply and its reference count
> >>>>>>>>>>> drops to zero, could it be disabled, causing an unexpected power loss for
> >>>>>>>>>>> downstream components?
> >>>>>>>>>>
> >>>>>>>>>> And this is a correct comment. Please provide missing supplies.
> >>>>>>>>>>
> >>>>>>>>> As per the Qualcomm system design, the parent-child supply relationship
> >>>>>>>>> is managed by the RPM firmware, not the Linux regulator framework. The
> >>>>>>>>> RPM ensures the parent supply is never disabled until all subsystem
> >>>>>>>>> votes are cleared.
> >>>>>>>>
> >>>>>>>> How is this different from other, previous platforms?
> >>>>>>>
> >>>>>>> This is not different. In the previous platforms too this is taken care from the
> >>>>>>> RPM/RPMH firmware side, the only case where we may need explicit vote to parent
> >>>>>>> is for non-rpmh/rpm regulator rails (like i2c based regulator pm8008), which
> >>>>>>> may have a RPM/RPMH regulator as a parent.
> >>>>>>>
> >>>>>>> Even on those previous targets the parent rail of all RPM/RPMH regulators are
> >>>>>>> internally voted by RPM/RPMH FW at proper voltage with required headroom
> >>>>>>> calculated based on the active child rails. This was done for all the
> >>>>>>> subsystems (including APPS) regulators.
> >>>>>>>
> >>>>>>> So no explicit handling from the APPS is required for parent supply.
> >>>>>>
> >>>>>> You are explaining the driver behaviour. But the question is about the
> >>>>>> hardware description. If there is no difference, please add necessary
> >>>>>> supplies back.
> >>>>>
> >>>>> I understand your concern about descibing the parent-child relation in the
> >>>>> devicetree, and given that we have been almost always followed this for all
> >>>>> the previous targets, it will expected of us to add them.
> >>>>
> >>>> Yes.
> >>>>
> >>>>>
> >>>>> However, we want to avoid the unnecessary access to the parent from APPS.
> >>>>
> >>>> Why? What is the reason? Do we want to do the same for all the
> >>>> platforms? Only for Shikra? Something else?
> >>>>
> >>>>> At the moment, I do not see a way to avoid that, if we add the parent
> >>>>> regulators.
> >>>>
> >>>> That depend on the answer to the previous question. In the end, we can
> >>>> make the driver ignore the parents by removing them from the regulator
> >>>> desc.
> >>>
> >>> Ok, this seems like a good suggestion, so you mean its ok if we define the
> >>> regulator desc's supply column with NULL? And only keep that in the DT?
> >>>
> >>> you mean like this?
> >>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/regulator/qcom-rpmh-regulator.c?h=v7.1#n1453
> >>>
> >>> (please let me know if i got that right. thanks)
> >>
> >> Yes. Don't forget to explain in the commit message, why you are doing
> >> so.
> >
> > Currently, Agatti uses the same PMIC, so we cannot set the driver
> > supply name reference to NULL. Since it's an older target,
> > we'll need to run a regression before making any driver-level changes.
> >
> > Additionally, the child-to-parent regulator ganging differs between
> > Shikra and Agatti:
> >
> > - On Agatti, l3 regulator is ganged with vdd_l13_l14_l15_l16
> > - On Shikra, l3 is ganged with vdd_l2_l3
>
> Is it configurable on the PMIC level? I was under the impression the
> supply maps are fixed in hardware. Is there a chance the agatti
> description is just wrong?
The supply ganging between child LDOs and parent supplies is not fixed
at the PMIC hardware level — it varies per platform based on system
design requirements. The same LDO can have a different parent supply on
different SoCs.
I have verified the Agatti parent-child supply mappings and they are
correct. The difference between Agatti and Shikra is a legitimate
platform-level design difference, not an error in the Agatti DT.
regards
Rakesh Kota
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v2 2/2] phy: spacemit: Add USB3/PCIe comb PHY driver for Spacemit K3
From: sashiko-bot @ 2026-07-03 2:19 UTC (permalink / raw)
To: Inochi Amaoto
Cc: linux-phy, vkoul, neil.armstrong, olteanv, robh, conor+dt,
devicetree
In-Reply-To: <20260703021024.495433-3-inochiama@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Hardware register clobbering due to missing read-modify-write operations in PHY initialization.
--
commit c71cb5c4ebfcb4fc5aff5c18a7769949e15dae55
Author: Inochi Amaoto <inochiama@gmail.com>
phy: spacemit: Add USB3/PCIe comb PHY driver for Spacemit K3
Adds a USB3/PCIe comb PHY driver for Spacemit K3. The comb PHY requires
configuring a syscon device for the correct mux configuration and needs
calibration before usage.
> diff --git a/drivers/phy/spacemit/phy-k3-common.c b/drivers/phy/spacemit/phy-k3-common.c
> new file mode 100644
> index 0000000000000..0b289e63db999
> --- /dev/null
> +++ b/drivers/phy/spacemit/phy-k3-common.c
[ ... ]
> + /* Power down 100MHz refclk buffer */
> + val = readl(base + PHY_PU_CK_REG);
> + val = u32_replace_bits(val, 0, PHY_PU_REFCLK_100);
> + writel(val, base + PHY_PU_CK_REG);
> +
> + /* Program PLL REG1 configure the SSC */
> + val = FIELD_PREP(PHY_PLL_SSC_MODE, PHY_PLL_SSC_MODE_DOWN_SPREAD1) |
> + FIELD_PREP(PHY_PLL_SSC_DEP_SEL, PHY_PLL_SSC_5000PPM) |
> + FIELD_PREP(PHY_PLL_FREF_SEL, PHY_PLL_FREF_24M);
> + writel(val, base + PHY_PLL_REG1);
[Severity: High]
Does this completely overwrite PHY_PLL_REG1 and zero out unspecified bits?
Unlike the PCIe initialization path which uses a read-modify-write for this
register, this direct writel() in k3_usb3phy_init_single() clobbers the
entire register. Could this cause important default settings or calibration
values to be lost?
[ ... ]
> + for (i = 0; i < lg->data->lanes; i++) {
> + void __iomem *lane_base = lg->base + lg->data->offsets[i];
> +
> + val = readl(lane_base + PCIE_RX_REG1);
> + val = u32_replace_bits(val, 0, 0x3);
> + writel(val, lane_base + PCIE_RX_REG1);
> + }
> +
> + val = readl(phy_base + PHY_PLL_REG2);
> + val |= BIT(20);
> + writel(val, phy_base + PHY_PLL_REG2);
> +
> + /* The write is needed as clock requires renegotiation */
> + val = FIELD_PREP(PCIE_RX_REFCLK_MODE, PCIE_RX_REFCLK_MODE_DRIVER) |
> + PCIE_RX_SEL_TRI_CODE |
> + FIELD_PREP(PCIE_RX_LEGACY, PCIE_RX_LEGACY_DEFAULT);
> + writel(val, phy_base + PCIE_RX_REG1);
[Severity: High]
Does this clobber the entire PCIE_RX_REG1 register for lane 0?
The preceding loop performs a read-modify-write on PCIE_RX_REG1 for all lanes,
but this direct writel() on phy_base (which points to lane 0) invalidates
that previous work and zeroes out any bits not explicitly set here.
Should this also use a read-modify-write operation to preserve the register
state?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703021024.495433-1-inochiama@gmail.com?part=2
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH v2 2/2] phy: spacemit: Add USB3/PCIe comb PHY driver for Spacemit K3
From: Inochi Amaoto @ 2026-07-03 2:10 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yixun Lan, Kees Cook, Gustavo A. R. Silva,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Inochi Amaoto, Alex Elder, Ze Huang
Cc: linux-phy, devicetree, linux-riscv, spacemit, linux-kernel,
linux-hardening, Yixun Lan, Longbin Li
In-Reply-To: <20260703021024.495433-1-inochiama@gmail.com>
The comb PHY on K3 requires to configure a syscon device for the
right mux configuration. And it requires calibration before any
usage.
Add USB3/PCIe comb PHY driver for Spacemit K3.
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
drivers/phy/spacemit/Kconfig | 16 ++
drivers/phy/spacemit/Makefile | 2 +
drivers/phy/spacemit/phy-k3-combo.c | 252 +++++++++++++++++
drivers/phy/spacemit/phy-k3-common.c | 391 +++++++++++++++++++++++++++
drivers/phy/spacemit/phy-k3-common.h | 27 ++
5 files changed, 688 insertions(+)
create mode 100644 drivers/phy/spacemit/phy-k3-combo.c
create mode 100644 drivers/phy/spacemit/phy-k3-common.c
create mode 100644 drivers/phy/spacemit/phy-k3-common.h
diff --git a/drivers/phy/spacemit/Kconfig b/drivers/phy/spacemit/Kconfig
index 50b0005acf66..5fdf18fce499 100644
--- a/drivers/phy/spacemit/Kconfig
+++ b/drivers/phy/spacemit/Kconfig
@@ -23,3 +23,19 @@ config PHY_SPACEMIT_K1_USB2
help
Enable this to support K1 USB 2.0 PHY driver. This driver takes care of
enabling and clock setup and will be used by K1 udc/ehci/otg/xhci driver.
+
+config PHY_SPACEMIT_K3_COMMON_OPS
+ tristate
+ select MFD_SYSCON
+ select GENERIC_PHY
+
+config PHY_SPACEMIT_K3_COMBO_PHY
+ tristate "SpacemiT K3 USB3/PCIe PHY support"
+ depends on (ARCH_SPACEMIT || COMPILE_TEST) && OF
+ depends on COMMON_CLK
+ select PHY_SPACEMIT_K3_COMMON_OPS
+ help
+ Enable this to support K3 USB3/PCIe combo PHY driver. This
+ driver takes care of enabling and clock setup and will be used
+ by K3 dwc3 driver.
+ If unsure, say N.
diff --git a/drivers/phy/spacemit/Makefile b/drivers/phy/spacemit/Makefile
index a821a21d6142..f679c1851b4f 100644
--- a/drivers/phy/spacemit/Makefile
+++ b/drivers/phy/spacemit/Makefile
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_PHY_SPACEMIT_K1_PCIE) += phy-k1-pcie.o
obj-$(CONFIG_PHY_SPACEMIT_K1_USB2) += phy-k1-usb2.o
+obj-$(CONFIG_PHY_SPACEMIT_K3_COMBO_PHY) += phy-k3-combo.o
+obj-$(CONFIG_PHY_SPACEMIT_K3_COMMON_OPS) += phy-k3-common.o
diff --git a/drivers/phy/spacemit/phy-k3-combo.c b/drivers/phy/spacemit/phy-k3-combo.c
new file mode 100644
index 000000000000..0bc08bb6247a
--- /dev/null
+++ b/drivers/phy/spacemit/phy-k3-combo.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * phy-k3-combo.c - SpacemiT K3 PCIe/USB3 Combo PHY Driver
+ *
+ * Copyright (c) 2025 SpacemiT Technology Co. Ltd
+ */
+
+#include <linux/bitfield.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mfd/syscon.h>
+#include <linux/iopoll.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/phy/phy.h>
+
+#include <dt-bindings/phy/phy.h>
+
+#include "phy-k3-common.h"
+
+/*
+ * The PCIE/USB Subsystem on SpacemiT K3 have 3 single lane PIPE3 PHYs
+ * (PHY2/3/4) shared by PCIE PortC/D and USB3 PortB/C/D.
+ *
+ * PMUA_PCIE_SUBSYS_MGMT[4:0]
+ *
+ * bit4 = 0 : PCIe A X8 mode, all 8 lanes dedicated to PCIe Port A
+ * 1 : PHY lanes shared between PCIe or USB according to [3:0]
+ *
+ * All PHY matrix combinations according to [4:0]:
+ *
+ * 0x0X : PCIe-A X8
+ * 0x10 : PCIe-C x2 (PHY2+PHY3) + PCIe-D x1 (PHY4)
+ * 0x11 : PCIe-C x2 (PHY2+PHY3) + USB-D (PHY4)
+ * 0x12 : PCIe-C x1 (PHY2) + USB-C (PHY3)
+ * 0x13 : PCIe-C x1 (PHY2) + USB-C (PHY3) + USB-D (PHY4)
+ * 0x14 : PCIe-C x1 (PHY3) + USB-B (PHY2)
+ * 0x15 : PCIe-C x1 (PHY3) + USB-B (PHY2) + USB-D (PHY4)
+ * 0x16 : USB-B (PHY2) + USB-C (PHY3) + PCIe D x1 (PHY4)
+ * 0x17 : USB-B (PHY2) + USB-C (PHY3) + USB-D (PHY4)
+ *
+ * So any USB Port B/C/D operation requires PCIe A X8 mode to be disabled.
+ */
+#define PMUA_PCIE_SUBSYS_MGMT 0x1d8
+#define PU_MATRIX_CONF_MASK GENMASK(4, 0)
+
+#define COMBPHY_MAX_SUBPHYS 6
+
+struct k3_combo_phy {
+ struct device *dev;
+ struct k3_lane_group groups[COMBPHY_MAX_SUBPHYS];
+ void __iomem *base;
+ struct regmap *apb_spare;
+};
+
+static const struct k3_phy_lane_group_data k3_combphy_lane_group0 = {
+ .lanes = 2,
+ .config = 0xff,
+ .mask = 0x00,
+ .offsets = {
+ 0x0, 0x400
+ },
+};
+
+static const struct k3_phy_lane_group_data k3_combphy_lane_group1 = {
+ .lanes = 2,
+ .config = 0xff,
+ .mask = 0x00,
+ .offsets = {
+ 0x100000, 0x100400
+ },
+};
+
+static const struct k3_phy_lane_group_data k3_combphy_lane_group2 = {
+ .lanes = 1,
+ .config = 0x14,
+ .mask = 0x14,
+ .offsets = {
+ 0x200000
+ },
+};
+
+static const struct k3_phy_lane_group_data k3_combphy_lane_group3 = {
+ .lanes = 1,
+ .config = 0x12,
+ .mask = 0x12,
+ .offsets = {
+ 0x300000
+ },
+};
+
+static const struct k3_phy_lane_group_data k3_combphy_lane_group4 = {
+ .lanes = 1,
+ .config = 0x11,
+ .mask = 0x11,
+ .offsets = {
+ 0x400000
+ },
+};
+
+static const struct k3_phy_lane_group_data k3_combphy_lane_group5 = {
+ .lanes = 1,
+ .config = 0xff,
+ .mask = 0x00,
+ .offsets = {
+ 0x500000
+ },
+};
+
+static const struct k3_phy_lane_group_data *k3_combphy_lane_datas[] = {
+ &k3_combphy_lane_group0,
+ &k3_combphy_lane_group1,
+ &k3_combphy_lane_group2,
+ &k3_combphy_lane_group3,
+ &k3_combphy_lane_group4,
+ &k3_combphy_lane_group5,
+};
+
+static int k3_combo_phy_init_lanes(struct k3_combo_phy *phy, unsigned int config)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(k3_combphy_lane_datas); i++) {
+ const struct k3_phy_lane_group_data *data = k3_combphy_lane_datas[i];
+ struct k3_lane_group *lg = &phy->groups[i];
+ const struct phy_ops *ops;
+ bool is_usb;
+
+ is_usb = (data->mask & config) == data->config;
+ if (is_usb)
+ ops = &k3_usb3_phy_ops;
+ else
+ ops = &k3_pcie_phy_ops;
+
+ dev_dbg(phy->dev, "phy %d is %s\n", i, is_usb ? "usb" : "pcie");
+
+ lg->phy = devm_phy_create(phy->dev, NULL, ops);
+ if (IS_ERR(lg->phy))
+ return PTR_ERR(lg->phy);
+
+ lg->is_pcie = !is_usb;
+ lg->data = data;
+ lg->base = phy->base;
+ phy_set_drvdata(lg->phy, lg);
+ }
+
+ return 0;
+}
+
+static int k3_combo_phy_update_config(struct regmap *apmu, unsigned int config)
+{
+ if (config & ~PU_MATRIX_CONF_MASK)
+ return -EINVAL;
+
+ return regmap_update_bits(apmu, PMUA_PCIE_SUBSYS_MGMT, PU_MATRIX_CONF_MASK, config);
+}
+
+static struct phy *k3_combo_phy_xlate(struct device *dev, const struct of_phandle_args *args)
+{
+ struct k3_combo_phy *phy = dev_get_drvdata(dev);
+ struct k3_lane_group *lg;
+
+ if (args->args_count != 2) {
+ dev_err(dev, "Invalid number of arguments\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (args->args[0] >= ARRAY_SIZE(k3_combphy_lane_datas)) {
+ dev_err(dev, "Invalid PHY id\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ lg = &phy->groups[args->args[0]];
+
+ if ((lg->is_pcie && args->args[1] != PHY_TYPE_PCIE) ||
+ (!lg->is_pcie && args->args[1] != PHY_TYPE_USB3)) {
+ dev_err(dev, "Invalid PHY mode\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ return lg->phy;
+}
+
+static int k3_combo_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ struct phy_provider *provider;
+ struct k3_combo_phy *phy;
+ struct regmap *apmu;
+ u32 config = 0;
+ int ret;
+
+ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+ if (!phy)
+ return -ENOMEM;
+
+ phy->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(phy->base))
+ return PTR_ERR(phy->base);
+
+ phy->apb_spare = syscon_regmap_lookup_by_phandle(node, "spacemit,apb-spare");
+ if (IS_ERR(phy->apb_spare))
+ return dev_err_probe(dev, PTR_ERR(phy->apb_spare),
+ "Failed to find APB SPARE syscon");
+
+ apmu = syscon_regmap_lookup_by_phandle_args(node, "spacemit,apmu", 1, &config);
+ if (IS_ERR(apmu))
+ return dev_err_probe(dev, PTR_ERR(apmu),
+ "Failed to find APMU syscon");
+
+ ret = k3_combo_phy_update_config(apmu, config);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to set lane configuration");
+
+ phy->dev = dev;
+ platform_set_drvdata(pdev, phy);
+
+ ret = k3_phy_calibrate(phy->apb_spare);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to calibrate phy");
+
+ ret = k3_combo_phy_init_lanes(phy, config);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to init lanes");
+
+ provider = devm_of_phy_provider_register(dev, k3_combo_phy_xlate);
+ if (IS_ERR(provider))
+ return dev_err_probe(dev, PTR_ERR(provider),
+ "Failed to register provider\n");
+
+ return 0;
+}
+
+static const struct of_device_id k3_combo_phy_of_match[] = {
+ { .compatible = "spacemit,k3-combo-phy" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, k3_combo_phy_of_match);
+
+static struct platform_driver k3_combo_phy_driver = {
+ .probe = k3_combo_phy_probe,
+ .driver = {
+ .name = "spacemit,k3-combo-phy",
+ .of_match_table = k3_combo_phy_of_match,
+ },
+};
+module_platform_driver(k3_combo_phy_driver);
+
+MODULE_DESCRIPTION("SpacemiT K3 USB3/PCIe combo PHY driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/spacemit/phy-k3-common.c b/drivers/phy/spacemit/phy-k3-common.c
new file mode 100644
index 000000000000..0b289e63db99
--- /dev/null
+++ b/drivers/phy/spacemit/phy-k3-common.c
@@ -0,0 +1,391 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/bitfield.h>
+#include <linux/cleanup.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/usb.h>
+
+#include <dt-bindings/phy/phy.h>
+
+#include "phy-k3-common.h"
+
+/* PHY Registers */
+#define PHY_VERSION 0x0
+
+#define PHY_RESET_CFG 0x04
+
+#define PHY_RESET_RXBUF_RST BIT(0)
+#define PHY_RESET_SOFT_RST_PCS BIT(1)
+#define PHY_RESET_SOFT_RST_AHB BIT(2)
+#define PHY_RESET_EN_SD_AFTER_LOCK BIT(6)
+
+#define PHY_CLK_CFG 0x08
+
+#define PHY_CLK_PLL_READY BIT(0)
+#define PHY_CLK_TXCLK_INV BIT(2)
+#define PHY_CLK_RXCLK_EN BIT(3)
+#define PHY_CLK_TXCLK_EN BIT(4)
+#define PHY_CLK_PCLK_EN BIT(5)
+#define PHY_CLK_PIPE_PCLK_EN BIT(6)
+#define PHY_CLK_REFCLK_FREQ GENMASK(10, 7)
+#define PHY_CLK_REFCLK_24M 2
+#define PHY_CLK_SW_INIT_DONE BIT(11)
+#define PHY_CLK_PU_SSC_OUT BIT(23)
+
+#define PHY_MODE_CFG 0x0C
+
+#define PHY_MODE_PCIE_INT_EN BIT(0)
+#define PHY_MODE_LFPS_TPERIOD GENMASK(9, 8)
+#define PHY_MODE_LFPS_TPERIOD_USB 3
+
+#define PHY_PU_SEL 0x40
+
+#define PHY_PU_CFG_STATUS BIT(9)
+#define PHY_PU_OVRD_STATUS BIT(10)
+
+#define PHY_PU_CK_REG 0x54
+
+#define PHY_PU_REFCLK_100 BIT(25)
+
+#define PHY_PLL_REG1 0x58
+
+#define PHY_PLL_FREF_SEL GENMASK(15, 13)
+#define PHY_PLL_FREF_24M 0x1
+#define PHY_PLL_SSC_DEP_SEL GENMASK(27, 24)
+#define PHY_PLL_SSC_5000PPM 0xa
+#define PHY_PLL_SSC_MODE GENMASK(29, 28)
+#define PHY_PLL_SSC_MODE_CENTER_SPREAD 0
+#define PHY_PLL_SSC_MODE_UP_SPREAD 1
+#define PHY_PLL_SSC_MODE_DOWN_SPREAD 2
+#define PHY_PLL_SSC_MODE_DOWN_SPREAD1 3
+
+#define PHY_PLL_REG2 0x5c
+
+#define PHY_PLL_SEL_REF100 BIT(21)
+
+/* PHY RX Register Definitions */
+#define PHY_RX_REG_A 0x60
+
+#define PHY_RX_REG0_MASK GENMASK(7, 0)
+#define PHY_RX_REG1_MASK GENMASK(15, 8)
+#define PHY_RX_REG2_MASK GENMASK(23, 16)
+#define PHY_RX_REG3_MASK GENMASK(31, 24)
+
+#define PHY_RX_REG0_RLOAD BIT(4)
+#define PHY_RX_REG1_RTERM GENMASK(11, 8)
+#define PHY_RX_REG1_RC_CALI GENMASK(15, 12)
+#define PHY_RX_REG2_CSEL GENMASK(19, 16)
+#define PHY_RX_REG2_FORCE_CSEL BIT(20)
+#define PHY_RX_REG2_PSEL GENMASK(23, 21)
+#define PHY_RX_REG3_I_LOAD GENMASK(26, 24)
+#define PHY_RX_REG3_SEL_CBOOST_CODE BIT(27)
+#define PHY_RX_REG3_ADJ_BIAS GENMASK(29, 28)
+#define PHY_RX_REG3_RDEG1 GENMASK(31, 30)
+
+#define PHY_RX_REG_B 0x64
+
+#define PHY_RX_REG4_MASK GENMASK(7, 0)
+#define PHY_RX_REG5_MASK GENMASK(15, 8)
+#define PHY_RX_REG6_MASK GENMASK(23, 16)
+
+#define PHY_RX_REGB_MASK GENMASK(23, 0)
+
+#define PHY_RX_REG4_RDEG2 GENMASK(2, 1)
+#define PHY_RX_REG4_ENVOS BIT(4)
+#define PHY_RX_REG4_RTERM_SEL BIT(5)
+#define PHY_RX_REG4_MANUAL_CFG BIT(7)
+#define PHY_RX_REG5_RCELL_VCM GENMASK(11, 8)
+#define PHY_RX_REG5_RCELL_BIAS GENMASK(15, 12)
+#define PHY_RX_REG6_H1_REG GENMASK(19, 16)
+#define PHY_RX_REG6_ADAPT_GAIN GENMASK(21, 20)
+#define PHY_RX_REG6_BYPASS_ADPT BIT(22)
+
+#define PHY_ADPT_CFG0 0x140
+#define PHY_ADPT_AFE_RST_OVRD_EN BIT(1)
+#define PHY_ADPT_AFE_RST_OVRD_VAL BIT(4)
+
+#define PHY_RXEQ_TIME 0xb4
+#define PHY_RXEQ_TIME_OVRD_POST_C_SOC BIT(21)
+#define PHY_RXEQ_TIME_CFG_AMP_SOC GENMASK(23, 22)
+#define PHY_RXEQ_TIME_AMP_SOC_650M 0
+#define PHY_RXEQ_TIME_AMP_SOC_800M 1
+#define PHY_RXEQ_TIME_AMP_SOC_870M 2
+#define PHY_RXEQ_TIME_AMP_SOC_900M 3
+#define PHY_RXEQ_TIME_OVRD_AMP_SOC BIT(24)
+
+#define PCIE_PU_ADDR_CLK_CFG 0x0008
+#define PHY_CLK_PLL_READY BIT(0)
+#define PCIE_INITAL_TIMER GENMASK(6, 3)
+#define CFG_INTERNAL_TIMER_ADJ GENMASK(10, 7)
+#define CFG_SW_PHY_INIT_DONE BIT(11)
+
+/* Lane RX/TX configuration (per‑lane, at lane_base) */
+#define PCIE_RX_REG1 0x050
+#define PCIE_RX_REFCLK_MODE GENMASK(1, 0)
+#define PCIE_RX_REFCLK_MODE_DRIVER 1
+#define PCIE_RX_SEL_TRI_CODE BIT(2)
+#define PCIE_RX_LEGACY GENMASK(15, 8)
+#define PCIE_RX_LEGACY_DEFAULT 0x65
+
+#define PCIE_TX_REG1 0x064
+
+#define PCIE_PLL_TIMEOUT 500000
+#define PCIE_POLL_DELAY 500
+
+static int k3_usb3phy_init_single(struct k3_lane_group *lg, void __iomem *base)
+{
+ struct phy *phy = lg->phy;
+ u32 val, tmp;
+ int ret;
+
+ /* Do not wait CDR lock before sampling data */
+ val = readl(base + PHY_RESET_CFG);
+ val = u32_replace_bits(val, 0, PHY_RESET_EN_SD_AFTER_LOCK);
+ writel(val, base + PHY_RESET_CFG);
+
+ /* Power down 100MHz refclk buffer */
+ val = readl(base + PHY_PU_CK_REG);
+ val = u32_replace_bits(val, 0, PHY_PU_REFCLK_100);
+ writel(val, base + PHY_PU_CK_REG);
+
+ /* Program PLL REG1 configure the SSC */
+ val = FIELD_PREP(PHY_PLL_SSC_MODE, PHY_PLL_SSC_MODE_DOWN_SPREAD1) |
+ FIELD_PREP(PHY_PLL_SSC_DEP_SEL, PHY_PLL_SSC_5000PPM) |
+ FIELD_PREP(PHY_PLL_FREF_SEL, PHY_PLL_FREF_24M);
+ writel(val, base + PHY_PLL_REG1);
+
+ /* Un-select 100MHz PLL reference */
+ val = readl(base + PHY_PLL_REG2);
+ val = u32_replace_bits(val, 0, PHY_PLL_SEL_REF100);
+ writel(val, base + PHY_PLL_REG2);
+
+ /* USB LFPS period configuration */
+ val = readl(base + PHY_MODE_CFG);
+ val = u32_replace_bits(val, PHY_MODE_LFPS_TPERIOD_USB, PHY_MODE_LFPS_TPERIOD);
+ writel(val, base + PHY_MODE_CFG);
+
+ /* Force AFE adaptation reset */
+ val = readl(base + PHY_ADPT_CFG0);
+ val |= PHY_ADPT_AFE_RST_OVRD_EN | PHY_ADPT_AFE_RST_OVRD_VAL;
+ writel(val, base + PHY_ADPT_CFG0);
+
+ /* Override driver amplitude value to 900m */
+ val = readl(base + PHY_RXEQ_TIME);
+ val |= PHY_RXEQ_TIME_OVRD_AMP_SOC;
+ val = u32_replace_bits(val, PHY_RXEQ_TIME_AMP_SOC_900M, PHY_RXEQ_TIME_CFG_AMP_SOC);
+ writel(val, base + PHY_RXEQ_TIME);
+
+ /* Configure RX parameters */
+ val = PHY_RX_REG0_RLOAD |
+ FIELD_PREP(PHY_RX_REG1_RTERM, 0x8) |
+ FIELD_PREP(PHY_RX_REG1_RC_CALI, 0x7) |
+ FIELD_PREP(PHY_RX_REG2_CSEL, 0x8) |
+ PHY_RX_REG2_FORCE_CSEL |
+ FIELD_PREP(PHY_RX_REG2_PSEL, 0x4) |
+ FIELD_PREP(PHY_RX_REG3_I_LOAD, 0x7) |
+ PHY_RX_REG3_SEL_CBOOST_CODE |
+ FIELD_PREP(PHY_RX_REG3_ADJ_BIAS, 0x1) |
+ FIELD_PREP(PHY_RX_REG3_RDEG1, 0x3);
+ writel(val, base + PHY_RX_REG_A);
+
+ val = readl(base + PHY_RX_REG_B);
+ tmp = FIELD_PREP(PHY_RX_REG4_RDEG2, 0x2) |
+ PHY_RX_REG4_ENVOS | PHY_RX_REG4_RTERM_SEL | PHY_RX_REG4_MANUAL_CFG |
+ FIELD_PREP(PHY_RX_REG5_RCELL_VCM, 0x8) |
+ FIELD_PREP(PHY_RX_REG5_RCELL_BIAS, 0x8) |
+ FIELD_PREP(PHY_RX_REG6_H1_REG, 0x8) |
+ FIELD_PREP(PHY_RX_REG6_ADAPT_GAIN, 0x2);
+ val = u32_replace_bits(val, tmp, PHY_RX_REGB_MASK);
+ writel(val, base + PHY_RX_REG_B);
+
+ /*
+ * Inform PHY that all PLL-related configuration is done.
+ * PLL will not start locking until PHY_CLK_SW_INIT_DONE is set.
+ */
+ val = PHY_CLK_SW_INIT_DONE | PHY_CLK_PU_SSC_OUT |
+ FIELD_PREP(PHY_CLK_REFCLK_FREQ, PHY_CLK_REFCLK_24M) |
+ PHY_CLK_RXCLK_EN | PHY_CLK_TXCLK_EN |
+ PHY_CLK_PCLK_EN | PHY_CLK_PIPE_PCLK_EN;
+ writel(val, base + PHY_CLK_CFG);
+
+ ret = readl_poll_timeout(base + PHY_CLK_CFG, val,
+ (val & PHY_CLK_PLL_READY),
+ PCIE_POLL_DELAY, PCIE_PLL_TIMEOUT);
+ if (ret) {
+ dev_err(&phy->dev, "PHY PLL polling timeout\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int k3_usb3phy_init(struct phy *phy)
+{
+ struct k3_lane_group *lg = phy_get_drvdata(phy);
+ int ret, i;
+
+ for (i = 0; i < lg->data->lanes; i++) {
+ ret = k3_usb3phy_init_single(lg, lg->base + lg->data->offsets[i]);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+const struct phy_ops k3_usb3_phy_ops = {
+ .init = k3_usb3phy_init,
+ .owner = THIS_MODULE,
+};
+EXPORT_SYMBOL_GPL(k3_usb3_phy_ops);
+
+static int k3_pcie_phy_init(struct phy *phy)
+{
+ struct k3_lane_group *lg = phy_get_drvdata(phy);
+ void __iomem *phy_base = lg->base + lg->data->offsets[0];
+ u32 val;
+ int ret;
+ int i;
+
+ val = readl(phy_base + PHY_PLL_REG1);
+ val = u32_replace_bits(val, 0x2, GENMASK(15, 12));
+ writel(val, phy_base + PHY_PLL_REG1);
+
+ val = readl(phy_base + PHY_PLL_REG2);
+ val = u32_replace_bits(val, 0, BIT(21));
+ writel(val, phy_base + PHY_PLL_REG2);
+
+ for (i = 0; i < lg->data->lanes; i++) {
+ void __iomem *lane_base = lg->base + lg->data->offsets[i];
+
+ val = readl(lane_base + PCIE_RX_REG1);
+ val = u32_replace_bits(val, 0, 0x3);
+ writel(val, lane_base + PCIE_RX_REG1);
+ }
+
+ val = readl(phy_base + PHY_PLL_REG2);
+ val |= BIT(20);
+ writel(val, phy_base + PHY_PLL_REG2);
+
+ /* The write is needed as clock requires renegotiation */
+ val = FIELD_PREP(PCIE_RX_REFCLK_MODE, PCIE_RX_REFCLK_MODE_DRIVER) |
+ PCIE_RX_SEL_TRI_CODE |
+ FIELD_PREP(PCIE_RX_LEGACY, PCIE_RX_LEGACY_DEFAULT);
+ writel(val, phy_base + PCIE_RX_REG1);
+
+ /* pll_reg1 of lane0, disable SSC: pll[27:24] = 0 */
+ val = readl(phy_base + PHY_PLL_REG1);
+ val = u32_replace_bits(val, 0, GENMASK(27, 24));
+ writel(val, phy_base + PHY_PLL_REG1);
+
+ for (i = 0; i < lg->data->lanes; i++) {
+ void __iomem *lane_base = lg->base + lg->data->offsets[i];
+
+ /* set cfg_tx_send_dummy_data to be 1'b1 for disable dash data */
+ val = readl(lane_base + PHY_PU_SEL);
+ val = u32_replace_bits(val, 1, BIT(13));
+ writel(val, lane_base + PHY_PU_SEL);
+
+ /* disable en_sample_data_after_cdr_locked */
+ val = readl(lane_base + PHY_RESET_CFG);
+ val = u32_replace_bits(val, 0, BIT(6));
+ writel(val, lane_base + PHY_RESET_CFG);
+
+ /* Dynamic Lock */
+ val = readl(lane_base + PHY_MODE_CFG);
+ val = u32_replace_bits(val, 1, BIT(2));
+ writel(val, lane_base + PHY_MODE_CFG);
+
+ val = FIELD_PREP(PHY_RX_REG0_MASK, 0x10) |
+ FIELD_PREP(PHY_RX_REG1_MASK, 0x78) |
+ FIELD_PREP(PHY_RX_REG2_MASK, 0x98) |
+ FIELD_PREP(PHY_RX_REG3_MASK, 0xdf);
+ writel(val, lane_base + PHY_RX_REG_A);
+
+ val = readl(lane_base + PHY_RX_REG_B);
+ val &= ~PHY_RX_REGB_MASK;
+ val |= FIELD_PREP(PHY_RX_REG4_MASK, 0xb4) |
+ FIELD_PREP(PHY_RX_REG5_MASK, 0x88) |
+ FIELD_PREP(PHY_RX_REG6_MASK, 0x28);
+ writel(val, lane_base + PHY_RX_REG_B);
+
+ /* Set init done */
+ val = readl(lane_base + PCIE_PU_ADDR_CLK_CFG);
+ val = u32_replace_bits(val, 1, CFG_SW_PHY_INIT_DONE);
+ writel(val, lane_base + PCIE_PU_ADDR_CLK_CFG);
+ }
+
+ ret = readl_poll_timeout(phy_base + PCIE_PU_ADDR_CLK_CFG, val,
+ (val & PHY_CLK_PLL_READY), PCIE_POLL_DELAY,
+ PCIE_PLL_TIMEOUT);
+ if (ret) {
+ dev_err(&lg->phy->dev, "PHY PLL lock timeout\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+const struct phy_ops k3_pcie_phy_ops = {
+ .init = k3_pcie_phy_init,
+ .owner = THIS_MODULE,
+};
+EXPORT_SYMBOL_GPL(k3_pcie_phy_ops);
+
+/* PHY rcal init requires APB_SPARE regmap access */
+
+#define APB_SPARE_PU_CAL 0x178
+#define PU_CAL BIT(17)
+
+#define APB_SPARE_RCAL_HSIO 0x17c
+#define APB_SPARE_PU_CAL_DONE BIT(8)
+#define RCAL_OVRD_PTRIM GENMASK(23, 20)
+#define RCAL_OVRD_NTRIM GENMASK(27, 24)
+#define RCAL_OVRD_PTRIM_EN BIT(28)
+#define RCAL_OVRD_NTRIM_EN BIT(29)
+#define RCAL_OVRD_STABLE_VAL BIT(30)
+#define RCAL_OVRD_STABLE_EN BIT(31)
+
+#define RCAL_OVRD_TRIM_EN (RCAL_OVRD_NTRIM_EN | RCAL_OVRD_PTRIM_EN)
+#define RCAL_OVRD_TRIM_MASK (RCAL_OVRD_NTRIM | RCAL_OVRD_PTRIM)
+
+#define PU_CAL_TIMEOUT 2000000
+
+static DEFINE_MUTEX(calibrate_lock);
+
+int k3_phy_calibrate(struct regmap *apb_spare)
+{
+ unsigned int val = 0;
+ int ret;
+
+ guard(mutex)(&calibrate_lock);
+
+ regmap_read(apb_spare, APB_SPARE_RCAL_HSIO, &val);
+ if (val & APB_SPARE_PU_CAL_DONE)
+ return 0;
+
+ regmap_update_bits(apb_spare, APB_SPARE_PU_CAL, PU_CAL,
+ PU_CAL);
+
+ ret = regmap_read_poll_timeout(apb_spare, APB_SPARE_RCAL_HSIO,
+ val, (val & APB_SPARE_PU_CAL_DONE), PCIE_POLL_DELAY,
+ PU_CAL_TIMEOUT);
+
+ if (ret)
+ regmap_update_bits(apb_spare, APB_SPARE_RCAL_HSIO,
+ RCAL_OVRD_TRIM_EN | RCAL_OVRD_STABLE_VAL |
+ RCAL_OVRD_TRIM_MASK | RCAL_OVRD_STABLE_EN,
+ RCAL_OVRD_TRIM_EN | RCAL_OVRD_STABLE_VAL |
+ FIELD_PREP(RCAL_OVRD_NTRIM, 0x6) |
+ FIELD_PREP(RCAL_OVRD_PTRIM, 0xa) |
+ RCAL_OVRD_STABLE_EN);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(k3_phy_calibrate);
+
+MODULE_DESCRIPTION("SpacemiT K3 PHY common ops");
+MODULE_LICENSE("GPL");
diff --git a/drivers/phy/spacemit/phy-k3-common.h b/drivers/phy/spacemit/phy-k3-common.h
new file mode 100644
index 000000000000..49009c3c313a
--- /dev/null
+++ b/drivers/phy/spacemit/phy-k3-common.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _PHY_K3_COMMON_H
+#define _PHY_K3_COMMON_H
+
+#include <linux/phy/phy.h>
+
+struct k3_phy_lane_group_data {
+ u32 lanes;
+ u8 config;
+ u8 mask;
+ u32 offsets[] __counted_by(lanes);
+};
+
+struct k3_lane_group {
+ const struct k3_phy_lane_group_data *data;
+ void __iomem *base;
+ struct phy *phy;
+ bool is_pcie;
+};
+
+extern const struct phy_ops k3_pcie_phy_ops;
+extern const struct phy_ops k3_usb3_phy_ops;
+
+int k3_phy_calibrate(struct regmap *apb_spare);
+
+#endif
--
2.55.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v2 1/2] dt-bindings: phy: Add Spacemit K3 USB3/PCIe comb phy support
From: Inochi Amaoto @ 2026-07-03 2:10 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yixun Lan, Kees Cook, Gustavo A. R. Silva,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Inochi Amaoto, Alex Elder, Ze Huang
Cc: linux-phy, devicetree, linux-riscv, spacemit, linux-kernel,
linux-hardening, Yixun Lan, Longbin Li
In-Reply-To: <20260703021024.495433-1-inochiama@gmail.com>
The USB3/PCIe comb PHY on the K3 is a complex PHY group that
can provide multiple phy for both PCIe and USB controller.
Its mux configuration is controlled by the APMU syscon device.
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
.../bindings/phy/spacemit,k3-combo-phy.yaml | 68 +++++++++++++++++++
1 file changed, 68 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/spacemit,k3-combo-phy.yaml
diff --git a/Documentation/devicetree/bindings/phy/spacemit,k3-combo-phy.yaml b/Documentation/devicetree/bindings/phy/spacemit,k3-combo-phy.yaml
new file mode 100644
index 000000000000..ed820cf697b8
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/spacemit,k3-combo-phy.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/spacemit,k3-combo-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Spacemit K3 PCIE/USB3 Comb PHY
+
+maintainers:
+ - Inochi Amaoto <inochiama@gmail.com>
+
+properties:
+ compatible:
+ const: spacemit,k3-combo-phy
+
+ reg:
+ maxItems: 1
+
+ "#phy-cells":
+ const: 2
+ description:
+ The first one is phy id, the second one is phy type. This
+ only supports types are PCIe and USB .
+
+ spacemit,apb-spare:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to APB SPARE system controller interface, used for
+ PHY calibration.
+
+ spacemit,apmu:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ items:
+ - items:
+ - description: phandle of APMU syscon
+ - description: configuration of the PHY lanes
+ description: |
+ Phandle to control PHY mux configuration. The configuration
+ is described as follows:
+ bit 4: 0 - PCIe A x8 mode, 1 - PCIe lane share mode
+ bit 3: 0 - PCIe A x4 mode, 1 - PCIe A x2 and PCIe B x2 mode
+ bit 2: 0 - PCIe C lane 0 is PCIe mode , 1 - USB mode
+ bit 1: 0 - PCIe C lane 1 is PCIe mode , 1 - USB mode
+ bit 0: 0 - PCIe D lane is PCIe mode , 1 - USB mode
+
+ The bit[3:0] is only valid when bit 4 is 1.
+
+ This mux control does not affect the PHY for PCIe E, it is always
+ in PCIe mode.
+
+required:
+ - compatible
+ - reg
+ - "#phy-cells"
+ - spacemit,apb-spare
+ - spacemit,apmu
+
+additionalProperties: false
+
+examples:
+ - |
+ phy@81d00000 {
+ compatible = "spacemit,k3-combo-phy";
+ reg = <0x81d00000 0x600000>;
+ #phy-cells = <2>;
+ spacemit,apb-spare = <&apb_spare>;
+ spacemit,apmu = <&apmu 0x00>;
+ };
--
2.55.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH v2 0/2] riscv: spacemit: Add K3 PCIe/USB comb phy support
From: Inochi Amaoto @ 2026-07-03 2:10 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Yixun Lan, Kees Cook, Gustavo A. R. Silva,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Inochi Amaoto, Alex Elder, Ze Huang
Cc: linux-phy, devicetree, linux-riscv, spacemit, linux-kernel,
linux-hardening, Yixun Lan, Longbin Li
The PCIe/USB comb phy on K3 is a big phy that contains multiple
standalone phys for each PCIe and USB controllers. This phy is
required to configure a syscon device for mux configuration and
calibration.
Changed from v1:
patch 1:
1. Add extra description for "#phy-cells" and "spacemit,apmu"
patch 2:
1. Fix multiple spelling errors and copy-paste errors.
2. Make some magic number as meaningful macros.
3. Remove USB3 set_speed() callback as it is not needed.
4. Fix the wrong land data config and mask.
Inochi Amaoto (2):
dt-bindings: phy: Add Spacemit K3 USB3/PCIe comb phy support
phy: spacemit: Add USB3/PCIe comb PHY driver for Spacemit K3
.../bindings/phy/spacemit,k3-combo-phy.yaml | 68 +++
drivers/phy/spacemit/Kconfig | 16 +
drivers/phy/spacemit/Makefile | 2 +
drivers/phy/spacemit/phy-k3-combo.c | 252 +++++++++++
drivers/phy/spacemit/phy-k3-common.c | 391 ++++++++++++++++++
drivers/phy/spacemit/phy-k3-common.h | 27 ++
6 files changed, 756 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/spacemit,k3-combo-phy.yaml
create mode 100644 drivers/phy/spacemit/phy-k3-combo.c
create mode 100644 drivers/phy/spacemit/phy-k3-common.c
create mode 100644 drivers/phy/spacemit/phy-k3-common.h
--
2.55.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v4 3/4] phy: qcom-qusb2: Add support for Shikra
From: Krishna Kurapati @ 2026-07-02 15:54 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Neil Armstrong, Vinod Koul, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Bjorn Andersson, Konrad Dybcio, Xiangxu Yin,
Johan Hovold, Loic Poulain, Shawn Guo, Abel Vesa, Wesley Cheng,
linux-arm-msm, linux-phy, devicetree, linux-kernel
In-Reply-To: <ym4zec5vw2mudnvhw36w6vkuqupbl6up4dqmhk2sqeabphotsf@sudiy6poyjyx>
On 7/2/2026 7:18 PM, Dmitry Baryshkov wrote:
> On Wed, Jul 01, 2026 at 10:20:50PM +0530, Krishna Kurapati wrote:
>> Add init sequence and phy configuration for Shikra.
>>
>> Signed-off-by: Krishna Kurapati <krishna.kurapati@oss.qualcomm.com>
>> ---
>> drivers/phy/qualcomm/phy-qcom-qusb2.c | 16 ++++++++++++++++
>> 1 file changed, 16 insertions(+)
>>
>> diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
>> index eb93015be841..ab7437e7b751 100644
>> --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
>> +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
>> @@ -381,6 +381,19 @@ static const struct qusb2_phy_cfg sdm660_phy_cfg = {
>> .autoresume_en = BIT(3),
>> };
>>
>> +static const struct qusb2_phy_cfg shikra_phy_cfg = {
>> + .tbl = qcs615_init_tbl,
>> + .tbl_num = ARRAY_SIZE(qcs615_init_tbl),
>> + .regs = ipq6018_regs_layout,
>
> msm8996_regs_layout (otherwise you are programming the wrong register).
>
ACK. Will send v5 on top of your upcoming v2.
Regards,
Krishna,
>> +
>> + .has_pll_test = true,
>> + .se_clk_scheme_default = true,
>> + .disable_ctrl = CLAMP_N_EN | FREEZIO_N | POWER_DOWN,
>> + .mask_core_ready = PLL_LOCKED,
>> + .autoresume_en = BIT(3),
>> + .update_tune1_with_efuse = false,
>> +};
>> +
>> static const struct qusb2_phy_cfg sm6115_phy_cfg = {
>> .tbl = sm6115_init_tbl,
>> .tbl_num = ARRAY_SIZE(sm6115_init_tbl),
>> @@ -958,6 +971,9 @@ static const struct of_device_id qusb2_phy_of_match_table[] = {
>> }, {
>> .compatible = "qcom,sdm660-qusb2-phy",
>> .data = &sdm660_phy_cfg,
>> + }, {
>> + .compatible = "qcom,shikra-qusb2-phy",
>> + .data = &shikra_phy_cfg,
>> }, {
>> .compatible = "qcom,sm4250-qusb2-phy",
>> .data = &sm6115_phy_cfg,
>> --
>> 2.34.1
>>
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox