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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/stmicro/stmmac/dwmac-visconti.c
Extension
.c
Size
7722 bytes
Lines
275
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 visconti_eth {
	void __iomem *reg;
	struct clk *phy_ref_clk;
	struct device *dev;
};

static int visconti_eth_set_clk_tx_rate(void *bsp_priv, struct clk *clk_tx_i,
					phy_interface_t interface, int speed)
{
	struct visconti_eth *dwmac = bsp_priv;
	unsigned long clk_sel, val;

	if (phy_interface_mode_is_rgmii(interface)) {
		switch (speed) {
		case SPEED_1000:
			clk_sel = ETHER_CLK_SEL_FREQ_SEL_125M;
			break;

		case SPEED_100:
			clk_sel = ETHER_CLK_SEL_FREQ_SEL_25M;
			break;

		case SPEED_10:
			clk_sel = ETHER_CLK_SEL_FREQ_SEL_2P5M;
			break;

		default:
			return -EINVAL;
		}

		/* Stop internal clock */
		val = readl(dwmac->reg + REG_ETHER_CLOCK_SEL);
		val &= ~(ETHER_CLK_SEL_RMII_CLK_EN |
			 ETHER_CLK_SEL_RX_TX_CLK_EN);
		val |= ETHER_CLK_SEL_TX_O_E_N_IN;
		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);

		/* Set Clock-Mux, Start clock, Set TX_O direction */
		val = clk_sel | ETHER_CLK_SEL_RX_CLK_EXT_SEL_RXC;
		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);

		val |= ETHER_CLK_SEL_RX_TX_CLK_EN;
		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);

		val &= ~ETHER_CLK_SEL_TX_O_E_N_IN;
		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
	} else if (interface == PHY_INTERFACE_MODE_RMII) {
		switch (speed) {
		case SPEED_100:
			clk_sel = ETHER_CLK_SEL_DIV_SEL_2;
			break;

		case SPEED_10:
			clk_sel = ETHER_CLK_SEL_DIV_SEL_20;
			break;

		default:
			return -EINVAL;
		}

		/* Stop internal clock */
		val = readl(dwmac->reg + REG_ETHER_CLOCK_SEL);
		val &= ~(ETHER_CLK_SEL_RMII_CLK_EN |
			 ETHER_CLK_SEL_RX_TX_CLK_EN);
		val |= ETHER_CLK_SEL_TX_O_E_N_IN;
		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);

		/* Set Clock-Mux, Start clock, Set TX_O direction */
		val = clk_sel | ETHER_CLK_SEL_RX_CLK_EXT_SEL_DIV |
		      ETHER_CLK_SEL_TX_CLK_EXT_SEL_DIV |
		      ETHER_CLK_SEL_TX_O_E_N_IN |
		      ETHER_CLK_SEL_RMII_CLK_SEL_RX_C;
		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);

		val |= ETHER_CLK_SEL_RMII_CLK_RST;
		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);

		val |= ETHER_CLK_SEL_RMII_CLK_EN | ETHER_CLK_SEL_RX_TX_CLK_EN;
		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);
	} else {
		/* Stop internal clock */
		val = readl(dwmac->reg + REG_ETHER_CLOCK_SEL);
		val &= ~(ETHER_CLK_SEL_RMII_CLK_EN |
			 ETHER_CLK_SEL_RX_TX_CLK_EN);
		val |= ETHER_CLK_SEL_TX_O_E_N_IN;
		writel(val, dwmac->reg + REG_ETHER_CLOCK_SEL);

		/* Set Clock-Mux, Start clock, Set TX_O direction */
		val = ETHER_CLK_SEL_RX_CLK_EXT_SEL_RXC |
		      ETHER_CLK_SEL_TX_CLK_EXT_SEL_TXC |

Annotation

Implementation Notes