drivers/net/pcs/pcs-mtk-lynxi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/pcs/pcs-mtk-lynxi.c
Extension
.c
Size
10652 bytes
Lines
374
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 mtk_pcs_lynxi {
	struct regmap		*regmap;
	u32			ana_rgc3;
	phy_interface_t		interface;
	struct			phylink_pcs pcs;
	u32			flags;
	struct fwnode_handle	*fwnode;
};

static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs)
{
	return container_of(pcs, struct mtk_pcs_lynxi, pcs);
}

static unsigned int mtk_pcs_lynxi_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:
		return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;

	default:
		return 0;
	}
}

static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs,
				    unsigned int neg_mode,
				    struct phylink_link_state *state)
{
	struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
	unsigned int bm, adv;

	/* Read the BMSR and LPA */
	regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm);
	regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv);

	phylink_mii_c22_pcs_decode_state(state, neg_mode,
					 FIELD_GET(SGMII_BMSR, bm),
					 FIELD_GET(SGMII_LPA, adv));
}

static int mtk_pcs_config_polarity(struct mtk_pcs_lynxi *mpcs,
				   phy_interface_t interface)
{
	struct fwnode_handle *fwnode = mpcs->fwnode, *pcs_fwnode;
	unsigned int pol, default_pol = PHY_POL_NORMAL;
	unsigned int val = 0;
	int ret;

	if (!fwnode)
		return 0;

	if (fwnode_property_read_bool(fwnode, "mediatek,pnswap"))
		default_pol = PHY_POL_INVERT;

	pcs_fwnode = fwnode_get_named_child_node(fwnode, "pcs");

	ret = phy_get_rx_polarity(pcs_fwnode, phy_modes(interface),
				  BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT),
				  default_pol, &pol);
	if (ret) {
		fwnode_handle_put(pcs_fwnode);
		return ret;
	}
	if (pol == PHY_POL_INVERT)
		val |= SGMII_PN_SWAP_RX;

	ret = phy_get_tx_polarity(pcs_fwnode, phy_modes(interface),
				  BIT(PHY_POL_NORMAL) | BIT(PHY_POL_INVERT),
				  default_pol, &pol);
	fwnode_handle_put(pcs_fwnode);
	if (ret)
		return ret;
	if (pol == PHY_POL_INVERT)
		val |= SGMII_PN_SWAP_TX;

	return regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL,
				  SGMII_PN_SWAP_RX | SGMII_PN_SWAP_TX, val);
}

static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode,
				phy_interface_t interface,
				const unsigned long *advertising,
				bool permit_pause_to_mac)
{
	struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
	bool mode_changed = false, changed;

Annotation

Implementation Notes