drivers/net/pcs/pcs-lynx.c

Source file repositories/reference/linux-study-clean/drivers/net/pcs/pcs-lynx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/pcs/pcs-lynx.c
Extension
.c
Size
9681 bytes
Lines
376
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 lynx_pcs {
	struct phylink_pcs pcs;
	struct mdio_device *mdio;
};

enum sgmii_speed {
	SGMII_SPEED_10		= 0,
	SGMII_SPEED_100		= 1,
	SGMII_SPEED_1000	= 2,
	SGMII_SPEED_2500	= 2,
};

#define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs)
#define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs)

static unsigned int lynx_pcs_inband_caps(struct phylink_pcs *pcs,
					 phy_interface_t interface)
{
	switch (interface) {
	case PHY_INTERFACE_MODE_1000BASEX:
	case PHY_INTERFACE_MODE_2500BASEX:
	case PHY_INTERFACE_MODE_SGMII:
	case PHY_INTERFACE_MODE_QSGMII:
		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;

	case PHY_INTERFACE_MODE_10GBASER:
		return LINK_INBAND_DISABLE;

	case PHY_INTERFACE_MODE_USXGMII:
	case PHY_INTERFACE_MODE_10G_QXGMII:
		return LINK_INBAND_ENABLE;

	default:
		return 0;
	}
}

static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs,
				       struct phylink_link_state *state)
{
	struct mii_bus *bus = pcs->bus;
	int addr = pcs->addr;
	int status, lpa;

	status = mdiobus_c45_read(bus, addr, MDIO_MMD_VEND2, MII_BMSR);
	if (status < 0)
		return;

	state->link = !!(status & MDIO_STAT1_LSTATUS);
	state->an_complete = !!(status & MDIO_AN_STAT1_COMPLETE);
	if (!state->link || !state->an_complete)
		return;

	lpa = mdiobus_c45_read(bus, addr, MDIO_MMD_VEND2, MII_LPA);
	if (lpa < 0)
		return;

	phylink_decode_usxgmii_word(state, lpa);
}

static void lynx_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg_mode,
			       struct phylink_link_state *state)
{
	struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs);

	switch (state->interface) {
	case PHY_INTERFACE_MODE_1000BASEX:
	case PHY_INTERFACE_MODE_2500BASEX:
	case PHY_INTERFACE_MODE_SGMII:
	case PHY_INTERFACE_MODE_QSGMII:
		phylink_mii_c22_pcs_get_state(lynx->mdio, neg_mode, state);
		break;
	case PHY_INTERFACE_MODE_USXGMII:
	case PHY_INTERFACE_MODE_10G_QXGMII:
		lynx_pcs_get_state_usxgmii(lynx->mdio, state);
		break;
	case PHY_INTERFACE_MODE_10GBASER:
		phylink_mii_c45_pcs_get_state(lynx->mdio, state);
		break;
	default:
		break;
	}

	dev_dbg(&lynx->mdio->dev,
		"mode=%s/%s/%s link=%u an_complete=%u\n",
		phy_modes(state->interface),
		phy_speed_to_str(state->speed),
		phy_duplex_to_str(state->duplex),
		state->link, state->an_complete);
}

Annotation

Implementation Notes