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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c
Extension
.c
Size
7733 bytes
Lines
287
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 thead_dwmac {
	struct plat_stmmacenet_data *plat;
	void __iomem *apb_base;
	struct device *dev;
};

static int thead_dwmac_set_phy_if(struct plat_stmmacenet_data *plat)
{
	struct thead_dwmac *dwmac = plat->bsp_priv;
	u32 phyif;

	switch (plat->phy_interface) {
	case PHY_INTERFACE_MODE_MII:
		phyif = GMAC_INTF_MII_GMII;
		break;
	case PHY_INTERFACE_MODE_RGMII:
	case PHY_INTERFACE_MODE_RGMII_ID:
	case PHY_INTERFACE_MODE_RGMII_TXID:
	case PHY_INTERFACE_MODE_RGMII_RXID:
		phyif = GMAC_INTF_RGMII;
		break;
	default:
		dev_err(dwmac->dev, "unsupported phy interface %s\n",
			phy_modes(plat->phy_interface));
		return -EINVAL;
	}

	writel(phyif, dwmac->apb_base + GMAC_INTF_CTRL);
	return 0;
}

static int thead_dwmac_set_txclk_dir(struct plat_stmmacenet_data *plat)
{
	struct thead_dwmac *dwmac = plat->bsp_priv;
	u32 txclk_dir;

	switch (plat->phy_interface) {
	case PHY_INTERFACE_MODE_MII:
		txclk_dir = TXCLK_DIR_INPUT;
		break;
	case PHY_INTERFACE_MODE_RGMII:
	case PHY_INTERFACE_MODE_RGMII_ID:
	case PHY_INTERFACE_MODE_RGMII_TXID:
	case PHY_INTERFACE_MODE_RGMII_RXID:
		txclk_dir = TXCLK_DIR_OUTPUT;
		break;
	default:
		dev_err(dwmac->dev, "unsupported phy interface %s\n",
			phy_modes(plat->phy_interface));
		return -EINVAL;
	}

	writel(txclk_dir, dwmac->apb_base + GMAC_TXCLK_OEN);
	return 0;
}

static int thead_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i,
				 phy_interface_t interface, int speed)
{
	struct thead_dwmac *dwmac = bsp_priv;
	struct plat_stmmacenet_data *plat;
	unsigned long rate;
	long tx_rate;
	u32 div, reg;

	plat = dwmac->plat;

	switch (plat->phy_interface) {
	/* For MII, rxc/txc is provided by phy */
	case PHY_INTERFACE_MODE_MII:
		return 0;

	case PHY_INTERFACE_MODE_RGMII:
	case PHY_INTERFACE_MODE_RGMII_ID:
	case PHY_INTERFACE_MODE_RGMII_RXID:
	case PHY_INTERFACE_MODE_RGMII_TXID:
		rate = clk_get_rate(plat->stmmac_clk);

		writel(0, dwmac->apb_base + GMAC_PLLCLK_DIV);

		tx_rate = rgmii_clock(speed);
		if (tx_rate < 0) {
			dev_err(dwmac->dev, "invalid speed %d\n", speed);
			return tx_rate;
		}

		div = rate / tx_rate;
		if (rate != tx_rate * div) {
			dev_err(dwmac->dev, "invalid gmac rate %lu\n", rate);
			return -EINVAL;

Annotation

Implementation Notes