From 50e54e80679b4ab45c84687c77309aebc6f7b981 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Wed, 2 Aug 2023 19:04:32 +0000 Subject: [PATCH] phy: rockchip: snps-pcie3: Add support for RK3588 Add support for the RK3588 variant to the driver. Code imported almost 1:1 from mainline linux driver. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- .../phy/rockchip/phy-rockchip-snps-pcie3.c | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c index 642819b1f6..a4392daf4c 100644 --- a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c +++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c @@ -27,6 +27,17 @@ #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, + }, { }, }; -- 2.39.5