[PATCH v2 4/7] phy: rockchip: snps-pcie3: Add bifurcation support for RK3568

Kever Yang kever.yang at rock-chips.com
Wed Sep 27 04:46:41 CEST 2023


On 2023/8/3 03:04, Jonas Karlman wrote:
> Configure aggregation or bifurcation mode on RK3568 based on the value
> of data-lanes property.
>
> Code imported almost 1:1 from mainline linux driver.
>
> Fixes: 6ec62b6ca698 ("phy: rockchip: Add Rockchip Synopsys PCIe 3.0 PHY")
> Signed-off-by: Jonas Karlman <jonas at kwiboo.se>
Reviewed-by: Kever Yang <kever.yang at rock-chips.com>

Thanks,
- Kever
> ---
> v2:
> - Add fixes tag
>
>   .../phy/rockchip/phy-rockchip-snps-pcie3.c    | 65 +++++++++++++++++--
>   1 file changed, 59 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
> index b76b5386bef0..642819b1f672 100644
> --- a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
> +++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
> @@ -16,9 +16,16 @@
>   #include <dm/device_compat.h>
>   #include <dm/lists.h>
>   
> -#define GRF_PCIE30PHY_CON1 0x4
> -#define GRF_PCIE30PHY_CON6 0x18
> -#define GRF_PCIE30PHY_CON9 0x24
> +/* Register for RK3568 */
> +#define GRF_PCIE30PHY_CON1			0x4
> +#define GRF_PCIE30PHY_CON6			0x18
> +#define GRF_PCIE30PHY_CON9			0x24
> +#define GRF_PCIE30PHY_DA_OCM			(BIT(15) | BIT(31))
> +#define GRF_PCIE30PHY_STATUS0			0x80
> +#define GRF_PCIE30PHY_WR_EN			(0xf << 16)
> +#define SRAM_INIT_DONE(reg)			(reg & BIT(14))
> +
> +#define RK3568_BIFURCATION_LANE_0_1		BIT(0)
>   
>   /**
>    * struct rockchip_p3phy_priv - RK DW PCIe PHY state
> @@ -27,12 +34,16 @@
>    * @phy_grf: The regmap for controlling pipe signal
>    * @p30phy: The reset signal for PHY
>    * @clks: The clocks for PHY
> + * @num_lanes: The number of lane to controller mappings
> + * @lanes: The lane to controller mapping
>    */
>   struct rockchip_p3phy_priv {
>   	void __iomem *mmio;
>   	struct regmap *phy_grf;
>   	struct reset_ctl p30phy;
>   	struct clk_bulk clks;
> +	int num_lanes;
> +	u32 lanes[4];
>   };
>   
>   struct rockchip_p3phy_ops {
> @@ -42,15 +53,40 @@ struct rockchip_p3phy_ops {
>   static int rockchip_p3phy_rk3568_init(struct phy *phy)
>   {
>   	struct rockchip_p3phy_priv *priv = dev_get_priv(phy->dev);
> +	bool bifurcation = false;
> +	int ret;
> +	u32 reg;
>   
>   	/* Deassert PCIe PMA output clamp mode */
> -	regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9,
> -		     (0x1 << 15) | (0x1 << 31));
> +	regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9, GRF_PCIE30PHY_DA_OCM);
> +
> +	for (int i = 0; i < priv->num_lanes; i++) {
> +		if (priv->lanes[i] > 1)
> +			bifurcation = true;
> +	}
> +
> +	/* Set bifurcation if needed, and it doesn't care RC/EP */
> +	if (bifurcation) {
> +		regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6,
> +			     GRF_PCIE30PHY_WR_EN | RK3568_BIFURCATION_LANE_0_1);
> +		regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON1,
> +			     GRF_PCIE30PHY_DA_OCM);
> +	} else {
> +		regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6,
> +			     GRF_PCIE30PHY_WR_EN & ~RK3568_BIFURCATION_LANE_0_1);
> +	}
>   
>   	reset_deassert(&priv->p30phy);
>   	udelay(1);
>   
> -	return 0;
> +	ret = regmap_read_poll_timeout(priv->phy_grf,
> +				       GRF_PCIE30PHY_STATUS0,
> +				       reg, 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 rk3568_ops = {
> @@ -103,6 +139,23 @@ static int rockchip_p3phy_probe(struct udevice *dev)
>   		return PTR_ERR(priv->phy_grf);
>   	}
>   
> +	ret = dev_read_size(dev, "data-lanes");
> +	if (ret > 0) {
> +		priv->num_lanes = ret / sizeof(u32);
> +		if (priv->num_lanes < 2 ||
> +		    priv->num_lanes > ARRAY_SIZE(priv->lanes)) {
> +			dev_err(dev, "unsupported data-lanes property size\n");
> +			return -EINVAL;
> +		}
> +
> +		ret = dev_read_u32_array(dev, "data-lanes", priv->lanes,
> +					 priv->num_lanes);
> +		if (ret) {
> +			dev_err(dev, "failed to read data-lanes property\n");
> +			return ret;
> +		}
> +	}
> +
>   	ret = reset_get_by_name(dev, "phy", &priv->p30phy);
>   	if (ret) {
>   		dev_err(dev, "no phy reset control specified\n");


More information about the U-Boot mailing list