drivers/phy/rockchip/phy-rockchip-snps-pcie3.c

Source file repositories/reference/linux-study-clean/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
Extension
.c
Size
10427 bytes
Lines
356
Domain
Driver Families
Bucket
drivers/phy
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct rockchip_p3phy_priv {
	const struct rockchip_p3phy_ops *ops;
	void __iomem *mmio;
	/* mode: RC, EP */
	int mode;
	/* pcie30_phymode: Aggregation, Bifurcation */
	int pcie30_phymode;
	struct regmap *phy_grf;
	struct regmap *pipe_grf;
	struct reset_control *p30phy;
	struct phy *phy;
	struct clk_bulk_data *clks;
	int num_clks;
	int num_lanes;
	u32 lanes[4];
	u32 rx_cmn_refclk_mode[4];
};

struct rockchip_p3phy_ops {
	int (*phy_init)(struct rockchip_p3phy_priv *priv);
};

static int rockchip_p3phy_set_mode(struct phy *phy, enum phy_mode mode, int submode)
{
	struct rockchip_p3phy_priv *priv = phy_get_drvdata(phy);

	/* Actually We don't care EP/RC mode, but just record it */
	switch (submode) {
	case PHY_MODE_PCIE_RC:
		priv->mode = PHY_MODE_PCIE_RC;
		break;
	case PHY_MODE_PCIE_EP:
		priv->mode = PHY_MODE_PCIE_EP;
		break;
	default:
		dev_err(&phy->dev, "%s, invalid mode\n", __func__);
		return -EINVAL;
	}

	return 0;
}

static int rockchip_p3phy_rk3568_init(struct rockchip_p3phy_priv *priv)
{
	struct phy *phy = priv->phy;
	bool bifurcation = false;
	int ret;
	u32 reg;

	/* Deassert PCIe PMA output clamp mode */
	regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9, GRF_PCIE30PHY_DA_OCM);

	for (int i = 0; i < priv->num_lanes; i++) {
		dev_info(&phy->dev, "lane number %d, val %d\n", i, priv->lanes[i]);
		if (priv->lanes[i] > 1)
			bifurcation = true;
	}

	/* Set bifurcation if needed, and it doesn't care RC/EP */
	if (bifurcation) {
		dev_info(&phy->dev, "bifurcation enabled\n");
		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 {
		dev_dbg(&phy->dev, "bifurcation disabled\n");
		regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6,
			     GRF_PCIE30PHY_WR_EN & ~RK3568_BIFURCATION_LANE_0_1);
	}

	reset_control_deassert(priv->p30phy);

	ret = regmap_read_poll_timeout(priv->phy_grf,
				       GRF_PCIE30PHY_STATUS0,
				       reg, SRAM_INIT_DONE(reg),
				       0, 500);
	if (ret)
		dev_err(&priv->phy->dev, "%s: lock failed 0x%x, check input refclk and power supply\n",
		       __func__, reg);
	return ret;
}

static const struct rockchip_p3phy_ops rk3568_ops = {
	.phy_init = rockchip_p3phy_rk3568_init,
};

static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
{
	u32 reg = 0;

Annotation

Implementation Notes