]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
phy: k1-usb: k3: add USB2 PHY support
authorYixun Lan <dlan@kernel.org>
Thu, 5 Mar 2026 01:00:52 +0000 (01:00 +0000)
committerVinod Koul <vkoul@kernel.org>
Sun, 10 May 2026 09:43:02 +0000 (15:13 +0530)
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.

Reviewed-by: Yao Zi <me@ziyao.cc>
Signed-off-by: Yixun Lan <dlan@kernel.org>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Link: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git/commit/?h=usb-next&id=c05cf9d274daf72dc7e433480cf2e0e888f6bd89
Link: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git/commit/?h=usb-next&id=00b4fe5be06aecd6426930de86b7cffc2330f4b8
Link: https://patch.msgid.link/20260305-11-k3-usb2-phy-v4-2-15554fb933bc@kernel.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/phy/spacemit/phy-k1-usb2.c

index 9215d0b223b2d697327388f044448eb61c5306d8..87b943d9111fff83da11731df6c3566f35ab2ce0 100644 (file)
@@ -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);