Misconfigured `PHP_GRF_PCIESEL` values are causing bifurcation issues,
for example on the FriendlyElec CM3588 NAS board which uses bifurcation
on both PCIe PCIe ports (all four lanes) to enable four M.2 NVMe
sockets. Without this fix, NVMe devices do not get recognized.

Correct the `PHP_GRF_PCIESEL` register configuration and simplify the
bifurcation logic, enabling proper PCIe bifurcation based on the
data-lanes property.

This fix is adapted from the upstream Linux commit by Michal Tomek:
f8020dfb311d ("phy: rockchip-snps-pcie3: fix bifurcation on rk3588")

Fixes: 50e54e80679b ("phy: rockchip: snps-pcie3: Add support for RK3588")
Signed-off-by: Sebastian Kropatsch <seb-...@mail.de>
---
 .../phy/rockchip/phy-rockchip-snps-pcie3.c    | 24 +++++++------------
 1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c 
b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
index 1c94875aaa..fadb77c25c 100644
--- a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
+++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
@@ -108,7 +108,7 @@ 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;
+       u8 mode = RK3588_LANE_AGGREGATION; /* Lane aggregation by default */
        int ret;
 
        /* Deassert PCIe PMA output clamp mode */
@@ -117,28 +117,20 @@ static int rockchip_p3phy_rk3588_init(struct phy *phy)
 
        /* 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;
+                       mode &= ~RK3588_LANE_AGGREGATION;
+               if (priv->lanes[i] == 3)
+                       mode |= RK3588_BIFURCATION_LANE_0_1;
+               if (priv->lanes[i] == 4)
+                       mode |= RK3588_BIFURCATION_LANE_2_3;
        }
 
+       reg = mode;
        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;
+       reg = mode & 3;
        if (reg)
                regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON,
                             (reg << 16) | reg);
-- 
2.43.0

Reply via email to