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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
Extension
.c
Size
10723 bytes
Lines
406
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 imx_dwmac_ops {
	u32 flags;
	u8 addr_width;
	bool mac_rgmii_txclk_auto_adj;

	int (*fix_soc_reset)(struct stmmac_priv *priv);
	int (*set_intf_mode)(struct imx_priv_data *dwmac, u8 phy_intf_sel);
	void (*fix_mac_speed)(void *priv, phy_interface_t interface,
			      int speed, unsigned int mode);
};

struct imx_priv_data {
	struct device *dev;
	struct clk *clk_tx;
	struct clk *clk_mem;
	struct regmap *intf_regmap;
	u32 intf_reg_off;
	bool rmii_refclk_ext;
	void __iomem *base_addr;

	const struct imx_dwmac_ops *ops;
	struct plat_stmmacenet_data *plat_dat;
};

static int imx8mp_set_intf_mode(struct imx_priv_data *dwmac, u8 phy_intf_sel)
{
	unsigned int val;

	val = FIELD_PREP(GPR_ENET_QOS_INTF_SEL_MASK, phy_intf_sel) |
	      GPR_ENET_QOS_CLK_GEN_EN;

	if (phy_intf_sel == PHY_INTF_SEL_RMII && !dwmac->rmii_refclk_ext)
		val |= GPR_ENET_QOS_CLK_TX_CLK_SEL;
	else if (phy_intf_sel == PHY_INTF_SEL_RGMII)
		val |= GPR_ENET_QOS_RGMII_EN;

	return regmap_update_bits(dwmac->intf_regmap, dwmac->intf_reg_off,
				  GPR_ENET_QOS_INTF_MODE_MASK, val);
};

static int
imx8dxl_set_intf_mode(struct imx_priv_data *dwmac, u8 phy_intf_sel)
{
	/* TBD: depends on imx8dxl scu interfaces to be upstreamed */
	return 0;
}

static int imx93_set_intf_mode(struct imx_priv_data *dwmac, u8 phy_intf_sel)
{
	unsigned int val;
	int ret;

	if (phy_intf_sel == PHY_INTF_SEL_RMII && dwmac->rmii_refclk_ext) {
		ret = regmap_clear_bits(dwmac->intf_regmap,
					dwmac->intf_reg_off +
					MX93_ENET_CLK_SEL_OFFSET,
					MX93_ENET_QOS_CLK_TX_SEL_MASK);
		if (ret)
			return ret;
	}

	val = FIELD_PREP(MX93_GPR_ENET_QOS_INTF_SEL_MASK, phy_intf_sel) |
	      MX93_GPR_ENET_QOS_ENABLE;

	return regmap_update_bits(dwmac->intf_regmap, dwmac->intf_reg_off,
				  MX93_GPR_ENET_QOS_INTF_SEL_MASK |
				  MX93_GPR_ENET_QOS_ENABLE, val);
};

static int imx_dwmac_clks_config(void *priv, bool enabled)
{
	struct imx_priv_data *dwmac = priv;
	int ret = 0;

	if (enabled) {
		ret = clk_prepare_enable(dwmac->clk_mem);
		if (ret) {
			dev_err(dwmac->dev, "mem clock enable failed\n");
			return ret;
		}

		ret = clk_prepare_enable(dwmac->clk_tx);
		if (ret) {
			dev_err(dwmac->dev, "tx clock enable failed\n");
			clk_disable_unprepare(dwmac->clk_mem);
			return ret;
		}
	} else {
		clk_disable_unprepare(dwmac->clk_tx);
		clk_disable_unprepare(dwmac->clk_mem);

Annotation

Implementation Notes