drivers/phy/qualcomm/phy-qcom-pcie2.c

Source file repositories/reference/linux-study-clean/drivers/phy/qualcomm/phy-qcom-pcie2.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/qualcomm/phy-qcom-pcie2.c
Extension
.c
Size
8909 bytes
Lines
333
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 qcom_phy {
	struct device *dev;
	void __iomem *base;

	struct regulator_bulk_data vregs[2];

	struct reset_control *phy_reset;
	struct reset_control *pipe_reset;
	struct clk *pipe_clk;
};

static int qcom_pcie2_phy_init(struct phy *phy)
{
	struct qcom_phy *qphy = phy_get_drvdata(phy);
	int ret;

	ret = reset_control_deassert(qphy->phy_reset);
	if (ret) {
		dev_err(qphy->dev, "cannot deassert pipe reset\n");
		return ret;
	}

	ret = regulator_bulk_enable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
	if (ret)
		reset_control_assert(qphy->phy_reset);

	return ret;
}

static int qcom_pcie2_phy_power_on(struct phy *phy)
{
	struct qcom_phy *qphy = phy_get_drvdata(phy);
	int ret;
	u32 val;

	/* Program REF_CLK source */
	val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2);
	val &= ~BIT(1);
	writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2);

	usleep_range(1000, 2000);

	/* Don't use PAD for refclock */
	val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2);
	val &= ~BIT(0);
	writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL2);

	/* Program SSP ENABLE */
	val = readl(qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL3);
	val |= BIT(0);
	writel(val, qphy->base + PCIE20_PARF_PHY_REFCLK_CTRL3);

	usleep_range(1000, 2000);

	/* Assert Phy SW Reset */
	val = readl(qphy->base + PCIE2_PHY_RESET_CTRL);
	val |= BIT(0);
	writel(val, qphy->base + PCIE2_PHY_RESET_CTRL);

	/* Program Tx Amplitude */
	val = readl(qphy->base + PCIE20_PARF_PCS_SWING_CTRL1);
	val &= ~0x7f;
	val |= TX_AMP_VAL;
	writel(val, qphy->base + PCIE20_PARF_PCS_SWING_CTRL1);

	val = readl(qphy->base + PCIE20_PARF_PCS_SWING_CTRL2);
	val &= ~0x7f;
	val |= TX_AMP_VAL;
	writel(val, qphy->base + PCIE20_PARF_PCS_SWING_CTRL2);

	/* Program De-Emphasis */
	val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH1);
	val &= ~0x3f;
	val |= TX_DEEMPH_GEN2_6DB_VAL;
	writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH1);

	val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH2);
	val &= ~0x3f;
	val |= TX_DEEMPH_GEN2_3_5DB_VAL;
	writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH2);

	val = readl(qphy->base + PCIE20_PARF_PCS_DEEMPH3);
	val &= ~0x3f;
	val |= TX_DEEMPH_GEN1_VAL;
	writel(val, qphy->base + PCIE20_PARF_PCS_DEEMPH3);

	/* Program Rx_Eq */
	val = readl(qphy->base + PCIE20_PARF_CONFIGBITS);
	val &= ~0x7;
	val |= PHY_RX0_EQ_GEN2_VAL;

Annotation

Implementation Notes