]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
phy: rockchip: snps-pcie3: Add support for RK3588
authorJonas Karlman <jonas@kwiboo.se>
Wed, 2 Aug 2023 19:04:32 +0000 (19:04 +0000)
committerKever Yang <kever.yang@rock-chips.com>
Sat, 7 Oct 2023 02:23:12 +0000 (10:23 +0800)
Add support for the RK3588 variant to the driver.

Code imported almost 1:1 from mainline linux driver.

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
drivers/phy/rockchip/phy-rockchip-snps-pcie3.c

index 642819b1f672e808cac6cc9f4db0f0e0b00965a0..a4392daf4c922624a0fb4270888c95fe78c91197 100644 (file)
 
 #define RK3568_BIFURCATION_LANE_0_1            BIT(0)
 
+/* Register for RK3588 */
+#define PHP_GRF_PCIESEL_CON                    0x100
+#define RK3588_PCIE3PHY_GRF_CMN_CON0           0x0
+#define RK3588_PCIE3PHY_GRF_PHY0_STATUS1       0x904
+#define RK3588_PCIE3PHY_GRF_PHY1_STATUS1       0xa04
+#define RK3588_SRAM_INIT_DONE(reg)             (reg & BIT(0))
+
+#define RK3588_BIFURCATION_LANE_0_1            BIT(0)
+#define RK3588_BIFURCATION_LANE_2_3            BIT(1)
+#define RK3588_LANE_AGGREGATION                        BIT(2)
+
 /**
  * struct rockchip_p3phy_priv - RK DW PCIe PHY state
  *
@@ -40,6 +51,7 @@
 struct rockchip_p3phy_priv {
        void __iomem *mmio;
        struct regmap *phy_grf;
+       struct regmap *pipe_grf;
        struct reset_ctl p30phy;
        struct clk_bulk clks;
        int num_lanes;
@@ -93,6 +105,66 @@ static const struct rockchip_p3phy_ops rk3568_ops = {
        .phy_init = rockchip_p3phy_rk3568_init,
 };
 
+static int rockchip_p3phy_rk3588_init(struct phy *phy)
+{
+       struct rockchip_p3phy_priv *priv = dev_get_priv(phy->dev);
+       u32 reg = 0;
+       u8 mode = 0;
+       int ret;
+
+       /* Deassert PCIe PMA output clamp mode */
+       regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0,
+                    BIT(8) | BIT(24));
+
+       /* Set bifurcation if needed */
+       for (int i = 0; i < priv->num_lanes; i++) {
+               if (!priv->lanes[i])
+                       mode |= (BIT(i) << 3);
+
+               if (priv->lanes[i] > 1)
+                       mode |= (BIT(i) >> 1);
+       }
+
+       if (!mode) {
+               reg = RK3588_LANE_AGGREGATION;
+       } else {
+               if (mode & (BIT(0) | BIT(1)))
+                       reg |= RK3588_BIFURCATION_LANE_0_1;
+
+               if (mode & (BIT(2) | BIT(3)))
+                       reg |= RK3588_BIFURCATION_LANE_2_3;
+       }
+
+       regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0,
+                    (0x7 << 16) | reg);
+
+       /* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */
+       reg = (mode & (BIT(6) | BIT(7))) >> 6;
+       if (reg)
+               regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON,
+                            (reg << 16) | reg);
+
+       reset_deassert(&priv->p30phy);
+       udelay(1);
+
+       ret = regmap_read_poll_timeout(priv->phy_grf,
+                                      RK3588_PCIE3PHY_GRF_PHY0_STATUS1,
+                                      reg, RK3588_SRAM_INIT_DONE(reg),
+                                      0, 500);
+       ret |= regmap_read_poll_timeout(priv->phy_grf,
+                                       RK3588_PCIE3PHY_GRF_PHY1_STATUS1,
+                                       reg, RK3588_SRAM_INIT_DONE(reg),
+                                       0, 500);
+       if (ret)
+               dev_err(phy->dev, "lock failed 0x%x\n", reg);
+
+       return ret;
+}
+
+static const struct rockchip_p3phy_ops rk3588_ops = {
+       .phy_init = rockchip_p3phy_rk3588_init,
+};
+
 static int rochchip_p3phy_init(struct phy *phy)
 {
        struct rockchip_p3phy_ops *ops =
@@ -139,6 +211,15 @@ static int rockchip_p3phy_probe(struct udevice *dev)
                return PTR_ERR(priv->phy_grf);
        }
 
+       if (device_is_compatible(dev, "rockchip,rk3588-pcie3-phy")) {
+               priv->pipe_grf =
+                       syscon_regmap_lookup_by_phandle(dev, "rockchip,pipe-grf");
+               if (IS_ERR(priv->pipe_grf)) {
+                       dev_err(dev, "failed to find rockchip,pipe_grf regmap\n");
+                       return PTR_ERR(priv->pipe_grf);
+               }
+       }
+
        ret = dev_read_size(dev, "data-lanes");
        if (ret > 0) {
                priv->num_lanes = ret / sizeof(u32);
@@ -181,6 +262,10 @@ static const struct udevice_id rockchip_p3phy_of_match[] = {
                .compatible = "rockchip,rk3568-pcie3-phy",
                .data = (ulong)&rk3568_ops,
        },
+       {
+               .compatible = "rockchip,rk3588-pcie3-phy",
+               .data = (ulong)&rk3588_ops,
+       },
        { },
 };