From 7a0b5195409f41589416fa4abccfbb1c729224cd Mon Sep 17 00:00:00 2001 From: Yixun Lan Date: Sat, 14 Feb 2026 20:29:14 +0800 Subject: [PATCH 1/3] dt-bindings: phy: spacemit: k3: add USB2 PHY support Introduce a compatible string for the USB2 PHY in SpacemiT K3 SoC. The IP of USB2 PHY mostly shares the same functionalities with K1 SoC, while has some register layout changes. Acked-by: Krzysztof Kozlowski Signed-off-by: Yixun Lan Signed-off-by: Linux RISC-V bot --- .../devicetree/bindings/phy/spacemit,usb2-phy.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/phy/spacemit,usb2-phy.yaml b/Documentation/devicetree/bindings/phy/spacemit,usb2-phy.yaml index 43eaca90d88c02..18025e5f60d691 100644 --- a/Documentation/devicetree/bindings/phy/spacemit,usb2-phy.yaml +++ b/Documentation/devicetree/bindings/phy/spacemit,usb2-phy.yaml @@ -4,14 +4,16 @@ $id: http://devicetree.org/schemas/phy/spacemit,usb2-phy.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: SpacemiT K1 SoC USB 2.0 PHY +title: SpacemiT K1/K3 SoC USB 2.0 PHY maintainers: - Ze Huang properties: compatible: - const: spacemit,k1-usb2-phy + enum: + - spacemit,k1-usb2-phy + - spacemit,k3-usb2-phy reg: maxItems: 1 From 0dddf326f8ca8ee2cf985f50d7a0ec53a1c16b40 Mon Sep 17 00:00:00 2001 From: Yixun Lan Date: Sat, 14 Feb 2026 20:29:15 +0800 Subject: [PATCH 2/3] phy: k1-usb: add disconnect function support A disconnect status BIT of USB2 PHY need to be cleared, otherwise it will fail to work properly during next connection when devices connect to roothub directly. Fixes: fe4bc1a08638 ("phy: spacemit: support K1 USB2.0 PHY controller") Signed-off-by: Yixun Lan Signed-off-by: Linux RISC-V bot --- drivers/phy/spacemit/phy-k1-usb2.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/phy/spacemit/phy-k1-usb2.c b/drivers/phy/spacemit/phy-k1-usb2.c index 34206138001250..959bf79c7a7260 100644 --- a/drivers/phy/spacemit/phy-k1-usb2.c +++ b/drivers/phy/spacemit/phy-k1-usb2.c @@ -48,6 +48,9 @@ #define PHY_CLK_HSTXP_EN BIT(3) /* clock hstxp enable */ #define PHY_HSTXP_MODE BIT(4) /* 0: force en_txp to be 1; 1: no force */ +#define PHY_K1_HS_HOST_DISC 0x40 +#define PHY_K1_HS_HOST_DISC_CLR BIT(0) + #define PHY_PLL_DIV_CFG 0x98 #define PHY_FDIV_FRACT_8_15 GENMASK(7, 0) #define PHY_FDIV_FRACT_16_19 GENMASK(11, 8) @@ -142,9 +145,20 @@ static int spacemit_usb2phy_exit(struct phy *phy) return 0; } +static int spacemit_usb2phy_disconnect(struct phy *phy, int port) +{ + struct spacemit_usb2phy *sphy = phy_get_drvdata(phy); + + regmap_update_bits(sphy->regmap_base, PHY_K1_HS_HOST_DISC, + PHY_K1_HS_HOST_DISC_CLR, PHY_K1_HS_HOST_DISC_CLR); + + return 0; +} + static const struct phy_ops spacemit_usb2phy_ops = { .init = spacemit_usb2phy_init, .exit = spacemit_usb2phy_exit, + .disconnect = spacemit_usb2phy_disconnect, .owner = THIS_MODULE, }; From ad648583f4d417d0a1e057e21dbcc5b4555fe7f4 Mon Sep 17 00:00:00 2001 From: Yixun Lan Date: Sat, 14 Feb 2026 20:29:16 +0800 Subject: [PATCH 3/3] phy: k1-usb: k3: add USB2 PHY support Add USB2 PHY support for SpacemiT K3 SoC. Register layout of handling USB disconnect operation has been changed, So introducing a platform data to distinguish the different SoCs. Signed-off-by: Yixun Lan Reviewed-by: Yao Zi Signed-off-by: Linux RISC-V bot --- drivers/phy/spacemit/phy-k1-usb2.c | 34 +++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/phy/spacemit/phy-k1-usb2.c b/drivers/phy/spacemit/phy-k1-usb2.c index 959bf79c7a7260..b4ba97481ddd9f 100644 --- a/drivers/phy/spacemit/phy-k1-usb2.c +++ b/drivers/phy/spacemit/phy-k1-usb2.c @@ -51,6 +51,9 @@ #define PHY_K1_HS_HOST_DISC 0x40 #define PHY_K1_HS_HOST_DISC_CLR BIT(0) +#define PHY_K3_HS_HOST_DISC 0x20 +#define PHY_K3_HS_HOST_DISC_CLR BIT(8) + #define PHY_PLL_DIV_CFG 0x98 #define PHY_FDIV_FRACT_8_15 GENMASK(7, 0) #define PHY_FDIV_FRACT_16_19 GENMASK(11, 8) @@ -145,7 +148,7 @@ static int spacemit_usb2phy_exit(struct phy *phy) return 0; } -static int spacemit_usb2phy_disconnect(struct phy *phy, int port) +static int spacemit_k1_usb2phy_disconnect(struct phy *phy, int port) { struct spacemit_usb2phy *sphy = phy_get_drvdata(phy); @@ -155,10 +158,27 @@ static int spacemit_usb2phy_disconnect(struct phy *phy, int port) return 0; } -static const struct phy_ops spacemit_usb2phy_ops = { +static int spacemit_k3_usb2phy_disconnect(struct phy *phy, int port) +{ + struct spacemit_usb2phy *sphy = phy_get_drvdata(phy); + + regmap_update_bits(sphy->regmap_base, PHY_K3_HS_HOST_DISC, + PHY_K3_HS_HOST_DISC_CLR, PHY_K3_HS_HOST_DISC_CLR); + + return 0; +} + +static const struct phy_ops spacemit_k1_usb2phy_ops = { .init = spacemit_usb2phy_init, .exit = spacemit_usb2phy_exit, - .disconnect = spacemit_usb2phy_disconnect, + .disconnect = spacemit_k1_usb2phy_disconnect, + .owner = THIS_MODULE, +}; + +static const struct phy_ops spacemit_k3_usb2phy_ops = { + .init = spacemit_usb2phy_init, + .exit = spacemit_usb2phy_exit, + .disconnect = spacemit_k3_usb2phy_disconnect, .owner = THIS_MODULE, }; @@ -167,12 +187,15 @@ static int spacemit_usb2phy_probe(struct platform_device *pdev) struct phy_provider *phy_provider; struct device *dev = &pdev->dev; struct spacemit_usb2phy *sphy; + const struct phy_ops *ops; void __iomem *base; sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL); if (!sphy) return -ENOMEM; + ops = device_get_match_data(dev); + sphy->clk = devm_clk_get_prepared(&pdev->dev, NULL); if (IS_ERR(sphy->clk)) return dev_err_probe(dev, PTR_ERR(sphy->clk), "Failed to get clock\n"); @@ -185,7 +208,7 @@ static int spacemit_usb2phy_probe(struct platform_device *pdev) if (IS_ERR(sphy->regmap_base)) return dev_err_probe(dev, PTR_ERR(sphy->regmap_base), "Failed to init regmap\n"); - sphy->phy = devm_phy_create(dev, NULL, &spacemit_usb2phy_ops); + sphy->phy = devm_phy_create(dev, NULL, ops); if (IS_ERR(sphy->phy)) return dev_err_probe(dev, PTR_ERR(sphy->phy), "Failed to create phy\n"); @@ -196,7 +219,8 @@ static int spacemit_usb2phy_probe(struct platform_device *pdev) } static const struct of_device_id spacemit_usb2phy_dt_match[] = { - { .compatible = "spacemit,k1-usb2-phy", }, + { .compatible = "spacemit,k1-usb2-phy", .data = &spacemit_k1_usb2phy_ops }, + { .compatible = "spacemit,k3-usb2-phy", .data = &spacemit_k3_usb2phy_ops }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, spacemit_usb2phy_dt_match);