drivers/phy/marvell/phy-armada38x-comphy.c

Source file repositories/reference/linux-study-clean/drivers/phy/marvell/phy-armada38x-comphy.c

File Facts

System
Linux kernel
Corpus path
drivers/phy/marvell/phy-armada38x-comphy.c
Extension
.c
Size
6351 bytes
Lines
277
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 a38x_comphy_lane {
	void __iomem *base;
	struct a38x_comphy *priv;
	unsigned int n;

	int port;
};

struct a38x_comphy {
	void __iomem *base;
	void __iomem *conf;
	struct device *dev;
	struct a38x_comphy_lane lane[MAX_A38X_COMPHY];
};

/*
 * Map serdes lanes and gbe ports to serdes mux configuration values:
 * row index = serdes lane,
 * column index = gbe port number.
 */
static const u8 gbe_mux[MAX_A38X_COMPHY][MAX_A38X_PORTS] = {
	{ 3, 0, 0 },
	{ 4, 5, 0 },
	{ 0, 4, 0 },
	{ 0, 0, 4 },
	{ 0, 3, 0 },
	{ 0, 0, 3 },
};

static void a38x_set_conf(struct a38x_comphy_lane *lane, bool enable)
{
	struct a38x_comphy *priv = lane->priv;
	u32 conf;

	if (priv->conf) {
		conf = readl_relaxed(priv->conf);
		if (enable)
			conf |= BIT(lane->port);
		else
			conf &= ~BIT(lane->port);
		writel(conf, priv->conf);
	}
}

static void a38x_comphy_set_reg(struct a38x_comphy_lane *lane,
				unsigned int offset, u32 mask, u32 value)
{
	u32 val;

	val = readl_relaxed(lane->base + offset) & ~mask;
	writel(val | value, lane->base + offset);
}

static void a38x_comphy_set_speed(struct a38x_comphy_lane *lane,
				  unsigned int gen_tx, unsigned int gen_rx)
{
	a38x_comphy_set_reg(lane, COMPHY_CFG1,
			    COMPHY_CFG1_GEN_TX_MSK | COMPHY_CFG1_GEN_RX_MSK,
			    COMPHY_CFG1_GEN_TX(gen_tx) |
		            COMPHY_CFG1_GEN_RX(gen_rx));
}

static int a38x_comphy_poll(struct a38x_comphy_lane *lane,
			    unsigned int offset, u32 mask, u32 value)
{
	u32 val;
	int ret;

	ret = readl_relaxed_poll_timeout_atomic(lane->base + offset, val,
						(val & mask) == value,
						1000, 150000);

	if (ret)
		dev_err(lane->priv->dev,
			"comphy%u: timed out waiting for status\n", lane->n);

	return ret;
}

/*
 * We only support changing the speed for comphys configured for GBE.
 * Since that is all we do, we only poll for PLL ready status.
 */
static int a38x_comphy_set_mode(struct phy *phy, enum phy_mode mode, int sub)
{
	struct a38x_comphy_lane *lane = phy_get_drvdata(phy);
	unsigned int gen;
	int ret;

	if (mode != PHY_MODE_ETHERNET)

Annotation

Implementation Notes