drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
Extension
.c
Size
8733 bytes
Lines
315
Domain
Driver Families
Bucket
drivers/net
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 sti_dwmac {
	phy_interface_t interface;	/* MII interface */
	bool ext_phyclk;	/* Clock from external PHY */
	u32 tx_retime_src;	/* TXCLK Retiming*/
	struct clk *clk;	/* PHY clock */
	u32 ctrl_reg;		/* GMAC glue-logic control register */
	int clk_sel_reg;	/* GMAC ext clk selection register */
	struct regmap *regmap;
	bool gmac_en;
	int speed;
	void (*fix_retime_src)(void *priv, phy_interface_t interface,
			       int speed, unsigned int mode);
};

struct sti_dwmac_of_data {
	void (*fix_retime_src)(void *priv, phy_interface_t interface,
			       int speed, unsigned int mode);
};

enum {
	TX_RETIME_SRC_NA = 0,
	TX_RETIME_SRC_TXCLK = 1,
	TX_RETIME_SRC_CLK_125,
	TX_RETIME_SRC_PHYCLK,
	TX_RETIME_SRC_CLKGEN,
};

static u32 stih4xx_tx_retime_val[] = {
	[TX_RETIME_SRC_TXCLK] = STIH4XX_ETH_SEL_TXCLK_NOT_CLK125,
	[TX_RETIME_SRC_CLK_125] = 0x0,
	[TX_RETIME_SRC_PHYCLK] = STIH4XX_ETH_SEL_TX_RETIME_CLK,
	[TX_RETIME_SRC_CLKGEN] = STIH4XX_ETH_SEL_TX_RETIME_CLK
				 | STIH4XX_ETH_SEL_INTERNAL_NOTEXT_PHYCLK,
};

static void stih4xx_fix_retime_src(void *priv, phy_interface_t interface,
				   int spd, unsigned int mode)
{
	struct sti_dwmac *dwmac = priv;
	u32 src = dwmac->tx_retime_src;
	u32 reg = dwmac->ctrl_reg;
	long freq = 0;

	if (dwmac->interface == PHY_INTERFACE_MODE_MII) {
		src = TX_RETIME_SRC_TXCLK;
	} else if (dwmac->interface == PHY_INTERFACE_MODE_RMII) {
		if (dwmac->ext_phyclk) {
			src = TX_RETIME_SRC_PHYCLK;
		} else {
			src = TX_RETIME_SRC_CLKGEN;
			freq = DWMAC_50MHZ;
		}
	} else if (phy_interface_mode_is_rgmii(dwmac->interface)) {
		/* On GiGa clk source can be either ext or from clkgen */
		freq = rgmii_clock(spd);

		if (spd != SPEED_1000 && freq > 0)
			/* Switch to clkgen for these speeds */
			src = TX_RETIME_SRC_CLKGEN;
	}

	if (src == TX_RETIME_SRC_CLKGEN && freq > 0)
		clk_set_rate(dwmac->clk, freq);

	regmap_update_bits(dwmac->regmap, reg, STIH4XX_RETIME_SRC_MASK,
			   stih4xx_tx_retime_val[src]);
}

static int sti_set_phy_intf_sel(void *bsp_priv, u8 phy_intf_sel)
{
	struct sti_dwmac *dwmac = bsp_priv;
	struct regmap *regmap;
	u32 reg, val;

	regmap = dwmac->regmap;
	reg = dwmac->ctrl_reg;

	if (dwmac->gmac_en)
		regmap_update_bits(regmap, reg, EN_MASK, EN);

	if (phy_intf_sel != PHY_INTF_SEL_GMII_MII &&
	    phy_intf_sel != PHY_INTF_SEL_RGMII &&
	    phy_intf_sel != PHY_INTF_SEL_SGMII &&
	    phy_intf_sel != PHY_INTF_SEL_RMII)
		phy_intf_sel = PHY_INTF_SEL_GMII_MII;

	regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK,
			   FIELD_PREP(MII_PHY_SEL_MASK, phy_intf_sel));

	val = (dwmac->interface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII;

Annotation

Implementation Notes