* [PATCH v2 1/5] dt-bindings: phy: rockchip,inno-usb2phy: Require GRF for RK3568/RV1108
2026-05-05 17:04 [PATCH v2 0/5] rockchip: Add USB 2.0 support for RK3528 Heiko Stuebner
@ 2026-05-05 17:04 ` Heiko Stuebner
2026-05-05 17:04 ` [PATCH v2 2/5] phy: rockchip: inno-usb2: Simplify rockchip,usbgrf handling Heiko Stuebner
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Heiko Stuebner @ 2026-05-05 17:04 UTC (permalink / raw)
To: vkoul
Cc: neil.armstrong, robh, krzk+dt, conor+dt, heiko, linux-phy,
devicetree, linux-arm-kernel, linux-rockchip, linux-kernel, jonas
From: Jonas Karlman <jonas@kwiboo.se>
Typically these Rockchip USB2 PHYs are fully contained within a single
GRF. However, for RK3568 and RV1108 regs to control the USB2 PHY is
located in a different GRF compared to the base address.
Update this binding to require rockchip,usbgrf for RK3568 and RV1108 to
properly reflect that the USB GRF is required to control the USB2 PHYs
on these variants. Also disable use of rockchip,usbgrf for variants
where it is not required.
This should not introduce any breakage as the affected usb2phy nodes for
RK3568 and RV1108 were added together with a rockchip,usbgrf phandle in
their initial commit.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
.../bindings/phy/rockchip,inno-usb2phy.yaml | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml b/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml
index 58e735b5dd05..b95c9e3e44fe 100644
--- a/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml
+++ b/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml
@@ -145,6 +145,20 @@ anyOf:
- host-port
allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - rockchip,rk3568-usb2phy
+ - rockchip,rv1108-usb2phy
+ then:
+ required:
+ - rockchip,usbgrf
+ else:
+ properties:
+ rockchip,usbgrf: false
+
- if:
properties:
compatible:
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 2/5] phy: rockchip: inno-usb2: Simplify rockchip,usbgrf handling
2026-05-05 17:04 [PATCH v2 0/5] rockchip: Add USB 2.0 support for RK3528 Heiko Stuebner
2026-05-05 17:04 ` [PATCH v2 1/5] dt-bindings: phy: rockchip,inno-usb2phy: Require GRF for RK3568/RV1108 Heiko Stuebner
@ 2026-05-05 17:04 ` Heiko Stuebner
2026-05-05 17:04 ` [PATCH v2 3/5] dt-bindings: phy: rockchip,inno-usb2phy: Add compatible for RK3528 Heiko Stuebner
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Heiko Stuebner @ 2026-05-05 17:04 UTC (permalink / raw)
To: vkoul
Cc: neil.armstrong, robh, krzk+dt, conor+dt, heiko, linux-phy,
devicetree, linux-arm-kernel, linux-rockchip, linux-kernel, jonas
From: Jonas Karlman <jonas@kwiboo.se>
The logic to decide if usbgrf or grf should be used is more complex than
it needs to be. For RK3568, RV1108 and soon RK3528 we can assign the
rockchip,usbgrf regmap directly to grf instead of doing a usbgrf and grf
dance.
Simplify the code to only use the grf regmap and handle the logic of
what regmap should be used in driver probe instead.
The only expected change from this is that RK3528 can be supported
because of an addition of a of_property_present() check.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 68 +++++--------------
1 file changed, 18 insertions(+), 50 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index 8f4c08e599aa..7cec45192393 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -228,7 +228,6 @@ struct rockchip_usb2phy_port {
* struct rockchip_usb2phy - usb2.0 phy driver data.
* @dev: pointer to device.
* @grf: General Register Files regmap.
- * @usbgrf: USB General Register Files regmap.
* @clks: array of phy input clocks.
* @clk480m: clock struct of phy output clk.
* @clk480m_hw: clock struct of phy output clk management.
@@ -246,7 +245,6 @@ struct rockchip_usb2phy_port {
struct rockchip_usb2phy {
struct device *dev;
struct regmap *grf;
- struct regmap *usbgrf;
struct clk_bulk_data *clks;
struct clk *clk480m;
struct clk_hw clk480m_hw;
@@ -261,11 +259,6 @@ struct rockchip_usb2phy {
struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS];
};
-static inline struct regmap *get_reg_base(struct rockchip_usb2phy *rphy)
-{
- return rphy->usbgrf == NULL ? rphy->grf : rphy->usbgrf;
-}
-
static inline int property_enable(struct regmap *base,
const struct usb2phy_reg *reg, bool en)
{
@@ -323,12 +316,11 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
{
struct rockchip_usb2phy *rphy =
container_of(hw, struct rockchip_usb2phy, clk480m_hw);
- struct regmap *base = get_reg_base(rphy);
int ret;
/* turn on 480m clk output if it is off */
- if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) {
- ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true);
+ if (!property_enabled(rphy->grf, &rphy->phy_cfg->clkout_ctl)) {
+ ret = property_enable(rphy->grf, &rphy->phy_cfg->clkout_ctl, true);
if (ret)
return ret;
@@ -343,19 +335,17 @@ static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
{
struct rockchip_usb2phy *rphy =
container_of(hw, struct rockchip_usb2phy, clk480m_hw);
- struct regmap *base = get_reg_base(rphy);
/* turn off 480m clk output */
- property_enable(base, &rphy->phy_cfg->clkout_ctl, false);
+ property_enable(rphy->grf, &rphy->phy_cfg->clkout_ctl, false);
}
static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw)
{
struct rockchip_usb2phy *rphy =
container_of(hw, struct rockchip_usb2phy, clk480m_hw);
- struct regmap *base = get_reg_base(rphy);
- return property_enabled(base, &rphy->phy_cfg->clkout_ctl);
+ return property_enabled(rphy->grf, &rphy->phy_cfg->clkout_ctl);
}
static unsigned long
@@ -574,7 +564,6 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
{
struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
- struct regmap *base = get_reg_base(rphy);
int ret;
dev_dbg(&rport->phy->dev, "port power on\n");
@@ -586,7 +575,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
if (ret)
return ret;
- ret = property_enable(base, &rport->port_cfg->phy_sus, false);
+ ret = property_enable(rphy->grf, &rport->port_cfg->phy_sus, false);
if (ret) {
clk_disable_unprepare(rphy->clk480m);
return ret;
@@ -615,7 +604,6 @@ static int rockchip_usb2phy_power_off(struct phy *phy)
{
struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
- struct regmap *base = get_reg_base(rphy);
int ret;
dev_dbg(&rport->phy->dev, "port power off\n");
@@ -623,7 +611,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy)
if (rport->suspended)
return 0;
- ret = property_enable(base, &rport->port_cfg->phy_sus, true);
+ ret = property_enable(rphy->grf, &rport->port_cfg->phy_sus, true);
if (ret)
return ret;
@@ -787,28 +775,22 @@ static const char *chg_to_string(enum power_supply_type chg_type)
static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
bool en)
{
- struct regmap *base = get_reg_base(rphy);
-
- property_enable(base, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
- property_enable(base, &rphy->phy_cfg->chg_det.idp_src_en, en);
+ property_enable(rphy->grf, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
+ property_enable(rphy->grf, &rphy->phy_cfg->chg_det.idp_src_en, en);
}
static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
bool en)
{
- struct regmap *base = get_reg_base(rphy);
-
- property_enable(base, &rphy->phy_cfg->chg_det.vdp_src_en, en);
- property_enable(base, &rphy->phy_cfg->chg_det.idm_sink_en, en);
+ property_enable(rphy->grf, &rphy->phy_cfg->chg_det.vdp_src_en, en);
+ property_enable(rphy->grf, &rphy->phy_cfg->chg_det.idm_sink_en, en);
}
static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
bool en)
{
- struct regmap *base = get_reg_base(rphy);
-
- property_enable(base, &rphy->phy_cfg->chg_det.vdm_src_en, en);
- property_enable(base, &rphy->phy_cfg->chg_det.idp_sink_en, en);
+ property_enable(rphy->grf, &rphy->phy_cfg->chg_det.vdm_src_en, en);
+ property_enable(rphy->grf, &rphy->phy_cfg->chg_det.idp_sink_en, en);
}
#define CHG_DCD_POLL_TIME (100 * HZ / 1000)
@@ -820,7 +802,6 @@ static void rockchip_chg_detect_work(struct work_struct *work)
struct rockchip_usb2phy_port *rport =
container_of(work, struct rockchip_usb2phy_port, chg_work.work);
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
- struct regmap *base = get_reg_base(rphy);
bool is_dcd, tmout, vout, vbus_attach;
unsigned long delay;
@@ -834,7 +815,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
rockchip_usb2phy_power_off(rport->phy);
/* put the controller in non-driving mode */
if (!vbus_attach)
- property_enable(base, &rphy->phy_cfg->chg_det.opmode, false);
+ property_enable(rphy->grf, &rphy->phy_cfg->chg_det.opmode, false);
/* Start DCD processing stage 1 */
rockchip_chg_enable_dcd(rphy, true);
rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
@@ -898,7 +879,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
case USB_CHG_STATE_DETECTED:
/* put the controller in normal mode */
if (!vbus_attach)
- property_enable(base, &rphy->phy_cfg->chg_det.opmode, true);
+ property_enable(rphy->grf, &rphy->phy_cfg->chg_det.opmode, true);
rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
dev_dbg(&rport->phy->dev, "charger = %s\n",
chg_to_string(rphy->chg_type));
@@ -1353,27 +1334,14 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
if (!rphy)
return -ENOMEM;
- if (!dev->parent || !dev->parent->of_node) {
+ if (!dev->parent || !dev->parent->of_node ||
+ of_property_present(np, "rockchip,usbgrf")) {
rphy->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbgrf");
- if (IS_ERR(rphy->grf)) {
- dev_err(dev, "failed to locate usbgrf\n");
- return PTR_ERR(rphy->grf);
- }
} else {
rphy->grf = syscon_node_to_regmap(dev->parent->of_node);
- if (IS_ERR(rphy->grf))
- return PTR_ERR(rphy->grf);
- }
-
- if (of_device_is_compatible(np, "rockchip,rv1108-usb2phy")) {
- rphy->usbgrf =
- syscon_regmap_lookup_by_phandle(dev->of_node,
- "rockchip,usbgrf");
- if (IS_ERR(rphy->usbgrf))
- return PTR_ERR(rphy->usbgrf);
- } else {
- rphy->usbgrf = NULL;
}
+ if (IS_ERR(rphy->grf))
+ return PTR_ERR(rphy->grf);
if (of_property_read_u32_index(np, "reg", 0, ®)) {
dev_err(dev, "the reg property is not assigned in %pOFn node\n", np);
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 3/5] dt-bindings: phy: rockchip,inno-usb2phy: Add compatible for RK3528
2026-05-05 17:04 [PATCH v2 0/5] rockchip: Add USB 2.0 support for RK3528 Heiko Stuebner
2026-05-05 17:04 ` [PATCH v2 1/5] dt-bindings: phy: rockchip,inno-usb2phy: Require GRF for RK3568/RV1108 Heiko Stuebner
2026-05-05 17:04 ` [PATCH v2 2/5] phy: rockchip: inno-usb2: Simplify rockchip,usbgrf handling Heiko Stuebner
@ 2026-05-05 17:04 ` Heiko Stuebner
2026-05-05 17:04 ` [PATCH v2 4/5] phy: rockchip: inno-usb2: Add clkout_ctl_phy support Heiko Stuebner
2026-05-05 17:04 ` [PATCH v2 5/5] phy: rockchip: inno-usb2: Add support for RK3528 Heiko Stuebner
4 siblings, 0 replies; 6+ messages in thread
From: Heiko Stuebner @ 2026-05-05 17:04 UTC (permalink / raw)
To: vkoul
Cc: neil.armstrong, robh, krzk+dt, conor+dt, heiko, linux-phy,
devicetree, linux-arm-kernel, linux-rockchip, linux-kernel, jonas
From: Jonas Karlman <jonas@kwiboo.se>
The embedded USB2 PHY on RK3528 is very similar to the one in RK3568,
the main difference being that it only uses two clocks instead of three.
Add compatible to support the USB2 PHY in RK3528.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
.../bindings/phy/rockchip,inno-usb2phy.yaml | 30 ++++++++++++++++---
1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml b/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml
index b95c9e3e44fe..f50fc69fbbe4 100644
--- a/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml
+++ b/Documentation/devicetree/bindings/phy/rockchip,inno-usb2phy.yaml
@@ -20,6 +20,7 @@ properties:
- rockchip,rk3328-usb2phy
- rockchip,rk3366-usb2phy
- rockchip,rk3399-usb2phy
+ - rockchip,rk3528-usb2phy
- rockchip,rk3562-usb2phy
- rockchip,rk3568-usb2phy
- rockchip,rk3576-usb2phy
@@ -41,11 +42,15 @@ properties:
maxItems: 3
clock-names:
- minItems: 1
- items:
+ oneOf:
- const: phyclk
- - const: aclk
- - const: aclk_slv
+ - items:
+ - const: phyclk
+ - const: pclk
+ - items:
+ - const: phyclk
+ - const: aclk
+ - const: aclk_slv
assigned-clocks:
description:
@@ -65,6 +70,9 @@ properties:
description: Muxed interrupt for both ports
maxItems: 1
+ power-domains:
+ maxItems: 1
+
resets:
maxItems: 2
@@ -150,6 +158,7 @@ allOf:
compatible:
contains:
enum:
+ - rockchip,rk3528-usb2phy
- rockchip,rk3568-usb2phy
- rockchip,rv1108-usb2phy
then:
@@ -218,6 +227,19 @@ allOf:
clock-names:
maxItems: 1
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - rockchip,rk3528-usb2phy
+ then:
+ properties:
+ clocks:
+ minItems: 2
+ clock-names:
+ minItems: 2
+
- if:
properties:
compatible:
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 4/5] phy: rockchip: inno-usb2: Add clkout_ctl_phy support
2026-05-05 17:04 [PATCH v2 0/5] rockchip: Add USB 2.0 support for RK3528 Heiko Stuebner
` (2 preceding siblings ...)
2026-05-05 17:04 ` [PATCH v2 3/5] dt-bindings: phy: rockchip,inno-usb2phy: Add compatible for RK3528 Heiko Stuebner
@ 2026-05-05 17:04 ` Heiko Stuebner
2026-05-05 17:04 ` [PATCH v2 5/5] phy: rockchip: inno-usb2: Add support for RK3528 Heiko Stuebner
4 siblings, 0 replies; 6+ messages in thread
From: Heiko Stuebner @ 2026-05-05 17:04 UTC (permalink / raw)
To: vkoul
Cc: neil.armstrong, robh, krzk+dt, conor+dt, heiko, linux-phy,
devicetree, linux-arm-kernel, linux-rockchip, linux-kernel, jonas
From: Jonas Karlman <jonas@kwiboo.se>
The 480m clk is controlled using regs in the PHY address space and not
in the USB GRF address space on e.g. RK3528 and RK3506.
Add a clkout_ctl_phy usb2phy_reg to handle enable/disable of the 480m
clk on these SoCs.
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 47 +++++++++++++++----
1 file changed, 38 insertions(+), 9 deletions(-)
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index 7cec45192393..d8879fcd4291 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -179,6 +179,7 @@ struct rockchip_usb2phy_cfg {
unsigned int num_ports;
int (*phy_tuning)(struct rockchip_usb2phy *rphy);
struct usb2phy_reg clkout_ctl;
+ struct usb2phy_reg clkout_ctl_phy;
const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS];
const struct rockchip_chg_det_reg chg_det;
};
@@ -228,6 +229,7 @@ struct rockchip_usb2phy_port {
* struct rockchip_usb2phy - usb2.0 phy driver data.
* @dev: pointer to device.
* @grf: General Register Files regmap.
+ * @phy_base: USB PHY regmap.
* @clks: array of phy input clocks.
* @clk480m: clock struct of phy output clk.
* @clk480m_hw: clock struct of phy output clk management.
@@ -245,6 +247,7 @@ struct rockchip_usb2phy_port {
struct rockchip_usb2phy {
struct device *dev;
struct regmap *grf;
+ struct regmap *phy_base;
struct clk_bulk_data *clks;
struct clk *clk480m;
struct clk_hw clk480m_hw;
@@ -312,15 +315,33 @@ static void rockchip_usb2phy_clk_bulk_disable(void *data)
clk_bulk_disable_unprepare(rphy->num_clks, rphy->clks);
}
-static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
+static void
+rockchip_usb2phy_clk480m_clkout_ctl(struct clk_hw *hw, struct regmap **base,
+ const struct usb2phy_reg **clkout_ctl)
{
struct rockchip_usb2phy *rphy =
container_of(hw, struct rockchip_usb2phy, clk480m_hw);
+
+ if (rphy->phy_cfg->clkout_ctl_phy.enable) {
+ *base = rphy->phy_base;
+ *clkout_ctl = &rphy->phy_cfg->clkout_ctl_phy;
+ } else {
+ *base = rphy->grf;
+ *clkout_ctl = &rphy->phy_cfg->clkout_ctl;
+ }
+}
+
+static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
+{
+ const struct usb2phy_reg *clkout_ctl;
+ struct regmap *base;
int ret;
+ rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl);
+
/* turn on 480m clk output if it is off */
- if (!property_enabled(rphy->grf, &rphy->phy_cfg->clkout_ctl)) {
- ret = property_enable(rphy->grf, &rphy->phy_cfg->clkout_ctl, true);
+ if (!property_enabled(base, clkout_ctl)) {
+ ret = property_enable(base, clkout_ctl, true);
if (ret)
return ret;
@@ -333,19 +354,23 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
{
- struct rockchip_usb2phy *rphy =
- container_of(hw, struct rockchip_usb2phy, clk480m_hw);
+ const struct usb2phy_reg *clkout_ctl;
+ struct regmap *base;
+
+ rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl);
/* turn off 480m clk output */
- property_enable(rphy->grf, &rphy->phy_cfg->clkout_ctl, false);
+ property_enable(base, clkout_ctl, false);
}
static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw)
{
- struct rockchip_usb2phy *rphy =
- container_of(hw, struct rockchip_usb2phy, clk480m_hw);
+ const struct usb2phy_reg *clkout_ctl;
+ struct regmap *base;
+
+ rockchip_usb2phy_clk480m_clkout_ctl(hw, &base, &clkout_ctl);
- return property_enabled(rphy->grf, &rphy->phy_cfg->clkout_ctl);
+ return property_enabled(base, clkout_ctl);
}
static unsigned long
@@ -1336,9 +1361,13 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
if (!dev->parent || !dev->parent->of_node ||
of_property_present(np, "rockchip,usbgrf")) {
+ rphy->phy_base = device_node_to_regmap(np);
+ if (IS_ERR(rphy->phy_base))
+ return PTR_ERR(rphy->phy_base);
rphy->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbgrf");
} else {
rphy->grf = syscon_node_to_regmap(dev->parent->of_node);
+ rphy->phy_base = rphy->grf;
}
if (IS_ERR(rphy->grf))
return PTR_ERR(rphy->grf);
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 5/5] phy: rockchip: inno-usb2: Add support for RK3528
2026-05-05 17:04 [PATCH v2 0/5] rockchip: Add USB 2.0 support for RK3528 Heiko Stuebner
` (3 preceding siblings ...)
2026-05-05 17:04 ` [PATCH v2 4/5] phy: rockchip: inno-usb2: Add clkout_ctl_phy support Heiko Stuebner
@ 2026-05-05 17:04 ` Heiko Stuebner
4 siblings, 0 replies; 6+ messages in thread
From: Heiko Stuebner @ 2026-05-05 17:04 UTC (permalink / raw)
To: vkoul
Cc: neil.armstrong, robh, krzk+dt, conor+dt, heiko, linux-phy,
devicetree, linux-arm-kernel, linux-rockchip, linux-kernel, jonas,
Jianwei Zheng
From: Jianwei Zheng <jianwei.zheng@rock-chips.com>
The RK3528 has a single USB2PHY with a otg and host port.
Add support for the RK3528 variant of USB2PHY.
PHY tuning for RK3528:
- Turn off differential receiver in suspend mode to save power
consumption.
- Set HS eye-height to 400mV instead of default 450mV.
- Choose the Tx fs/ls data as linestate from TX driver for otg port
which uses dwc3 controller to improve fs/ls devices compatibility with
long cables.
Undocumented magic-values are based on the linux-stan-6.1-rkr5 tag of
the vendor-kernel.
Signed-off-by: Jianwei Zheng <jianwei.zheng@rock-chips.com>
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 84 +++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index d8879fcd4291..133cfd6624e8 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -1511,6 +1511,38 @@ static int rk3128_usb2phy_tuning(struct rockchip_usb2phy *rphy)
BIT(2) << BIT_WRITEABLE_SHIFT | 0);
}
+static int rk3528_usb2phy_tuning(struct rockchip_usb2phy *rphy)
+{
+ int ret;
+
+ /* Turn off otg port differential receiver in suspend mode */
+ ret = regmap_write(rphy->phy_base, 0x30, BIT(18) | 0x0000);
+ if (ret)
+ return ret;
+
+ /* Turn off host port differential receiver in suspend mode */
+ ret = regmap_write(rphy->phy_base, 0x430, BIT(18) | 0x0000);
+ if (ret)
+ return ret;
+
+ /* Set otg port HS eye height to 400mv (default is 450mv) */
+ ret = regmap_write(rphy->phy_base, 0x30, GENMASK(22, 20) | 0x0000);
+ if (ret)
+ return ret;
+
+ /* Set host port HS eye height to 400mv (default is 450mv) */
+ ret = regmap_write(rphy->phy_base, 0x430, GENMASK(22, 20) | 0x0000);
+ if (ret)
+ return ret;
+
+ /* Choose the Tx fs/ls data as linestate from TX driver for otg port */
+ ret = regmap_write(rphy->phy_base, 0x94, GENMASK(22, 19) | 0x0018);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int rk3576_usb2phy_tuning(struct rockchip_usb2phy *rphy)
{
int ret;
@@ -1924,6 +1956,57 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
{ /* sentinel */ }
};
+static const struct rockchip_usb2phy_cfg rk3528_phy_cfgs[] = {
+ {
+ .reg = 0xffdf0000,
+ .num_ports = 2,
+ .phy_tuning = rk3528_usb2phy_tuning,
+ .clkout_ctl_phy = { 0x041c, 7, 2, 0, 0x27 },
+ .port_cfgs = {
+ [USB2PHY_PORT_OTG] = {
+ .phy_sus = { 0x004c, 8, 0, 0, 0x1d1 },
+ .bvalid_det_en = { 0x0074, 3, 2, 0, 3 },
+ .bvalid_det_st = { 0x0078, 3, 2, 0, 3 },
+ .bvalid_det_clr = { 0x007c, 3, 2, 0, 3 },
+ .idfall_det_en = { 0x0074, 5, 5, 0, 1 },
+ .idfall_det_st = { 0x0078, 5, 5, 0, 1 },
+ .idfall_det_clr = { 0x007c, 5, 5, 0, 1 },
+ .idrise_det_en = { 0x0074, 4, 4, 0, 1 },
+ .idrise_det_st = { 0x0078, 4, 4, 0, 1 },
+ .idrise_det_clr = { 0x007c, 4, 4, 0, 1 },
+ .ls_det_en = { 0x0074, 0, 0, 0, 1 },
+ .ls_det_st = { 0x0078, 0, 0, 0, 1 },
+ .ls_det_clr = { 0x007c, 0, 0, 0, 1 },
+ .utmi_avalid = { 0x006c, 1, 1, 0, 1 },
+ .utmi_bvalid = { 0x006c, 0, 0, 0, 1 },
+ .utmi_id = { 0x006c, 6, 6, 0, 1 },
+ .utmi_ls = { 0x006c, 5, 4, 0, 1 },
+ },
+ [USB2PHY_PORT_HOST] = {
+ .phy_sus = { 0x005c, 8, 0, 0x1d2, 0x1d1 },
+ .ls_det_en = { 0x0090, 0, 0, 0, 1 },
+ .ls_det_st = { 0x0094, 0, 0, 0, 1 },
+ .ls_det_clr = { 0x0098, 0, 0, 0, 1 },
+ .utmi_ls = { 0x006c, 13, 12, 0, 1 },
+ .utmi_hstdet = { 0x006c, 15, 15, 0, 1 },
+ }
+ },
+ .chg_det = {
+ .opmode = { 0x004c, 3, 0, 5, 1 },
+ .cp_det = { 0x006c, 19, 19, 0, 1 },
+ .dcp_det = { 0x006c, 18, 18, 0, 1 },
+ .dp_det = { 0x006c, 20, 20, 0, 1 },
+ .idm_sink_en = { 0x0058, 1, 1, 0, 1 },
+ .idp_sink_en = { 0x0058, 0, 0, 0, 1 },
+ .idp_src_en = { 0x0058, 2, 2, 0, 1 },
+ .rdm_pdwn_en = { 0x0058, 3, 3, 0, 1 },
+ .vdm_src_en = { 0x0058, 5, 5, 0, 1 },
+ .vdp_src_en = { 0x0058, 4, 4, 0, 1 },
+ },
+ },
+ { /* sentinel */ }
+};
+
static const struct rockchip_usb2phy_cfg rk3562_phy_cfgs[] = {
{
.reg = 0xff740000,
@@ -2291,6 +2374,7 @@ static const struct of_device_id rockchip_usb2phy_dt_match[] = {
{ .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
+ { .compatible = "rockchip,rk3528-usb2phy", .data = &rk3528_phy_cfgs },
{ .compatible = "rockchip,rk3562-usb2phy", .data = &rk3562_phy_cfgs },
{ .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs },
{ .compatible = "rockchip,rk3576-usb2phy", .data = &rk3576_phy_cfgs },
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread