drivers/phy/freescale/phy-fsl-imx8qm-hsio.c

Source file repositories/reference/linux-study-clean/drivers/phy/freescale/phy-fsl-imx8qm-hsio.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/freescale/phy-fsl-imx8qm-hsio.c
Extension
.c
Size
16969 bytes
Lines
615
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 imx_hsio_drvdata {
	int lane_num;
};

struct imx_hsio_lane {
	u32 ctrl_index;
	u32 ctrl_off;
	u32 idx;
	u32 phy_off;
	u32 phy_type;
	const char * const *clk_names;
	struct clk_bulk_data clks[LANE_NUM_CLKS];
	struct imx_hsio_priv *priv;
	struct phy *phy;
	enum phy_mode phy_mode;
};

struct imx_hsio_priv {
	void __iomem *base;
	struct device *dev;
	struct mutex lock;
	const char *hsio_cfg;
	const char *refclk_pad;
	u32 open_cnt;
	struct regmap *phy;
	struct regmap *ctrl;
	struct regmap *misc;
	const struct imx_hsio_drvdata *drvdata;
	struct imx_hsio_lane lane[MAX_NUM_LANE];
};

static const char * const lan0_pcie_clks[] = {"apb_pclk0", "pclk0", "ctl0_crr",
					      "phy0_crr", "misc_crr"};
static const char * const lan1_pciea_clks[] = {"apb_pclk1", "pclk1", "ctl0_crr",
					       "phy0_crr", "misc_crr"};
static const char * const lan1_pcieb_clks[] = {"apb_pclk1", "pclk1", "ctl1_crr",
					       "phy0_crr", "misc_crr"};
static const char * const lan2_pcieb_clks[] = {"apb_pclk2", "pclk2", "ctl1_crr",
					       "phy1_crr", "misc_crr"};
static const char * const lan2_sata_clks[] = {"pclk2", "epcs_tx", "epcs_rx",
					      "phy1_crr", "misc_crr"};

static const struct regmap_config regmap_config = {
	.reg_bits = 32,
	.val_bits = 32,
	.reg_stride = 4,
};

static int imx_hsio_init(struct phy *phy)
{
	int ret, i;
	struct imx_hsio_lane *lane = phy_get_drvdata(phy);
	struct imx_hsio_priv *priv = lane->priv;
	struct device *dev = priv->dev;

	/* Assign clocks refer to different modes */
	switch (lane->phy_type) {
	case PHY_TYPE_PCIE:
		lane->phy_mode = PHY_MODE_PCIE;
		if (lane->ctrl_index == 0) { /* PCIEA */
			lane->ctrl_off = 0;
			lane->phy_off = 0;

			for (i = 0; i < LANE_NUM_CLKS; i++) {
				if (lane->idx == 0)
					lane->clks[i].id = lan0_pcie_clks[i];
				else
					lane->clks[i].id = lan1_pciea_clks[i];
			}
		} else { /* PCIEB */
			if (lane->idx == 0) { /* i.MX8QXP */
				lane->ctrl_off = 0;
				lane->phy_off = 0;
			} else {
				/*
				 * On i.MX8QM, only second or third lane can be
				 * bound to PCIEB.
				 */
				lane->ctrl_off = SZ_64K;
				if (lane->idx == 1)
					lane->phy_off = 0;
				else /* the third lane is bound to PCIEB */
					lane->phy_off = SZ_64K;
			}

			for (i = 0; i < LANE_NUM_CLKS; i++) {
				if (lane->idx == 1)
					lane->clks[i].id = lan1_pcieb_clks[i];
				else if (lane->idx == 2)
					lane->clks[i].id = lan2_pcieb_clks[i];

Annotation

Implementation Notes