drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
Extension
.c
Size
20510 bytes
Lines
752
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 stmmac_clk_rate {
	unsigned long rate;
	u8 cr;
};

/* The standard clk_csr_i to GMII_Address CR field mapping. The rate provided
 * in this table is the exclusive maximum frequency for the divisor. The
 * comments for each entry give the divisor and the resulting range of MDC
 * clock frequencies.
 */
static const struct stmmac_clk_rate stmmac_std_csr_to_mdc[] = {
	{ CSR_F_800M, ~0 },
	{ CSR_F_500M, STMMAC_CSR_500_800M },
	{ CSR_F_300M, STMMAC_CSR_300_500M },
	{ CSR_F_250M, STMMAC_CSR_250_300M },
	{ CSR_F_150M, STMMAC_CSR_150_250M },
	{ CSR_F_100M, STMMAC_CSR_100_150M },
	{ CSR_F_60M,  STMMAC_CSR_60_100M },
	{ CSR_F_35M,  STMMAC_CSR_35_60M },
	{ CSR_F_20M,  STMMAC_CSR_20_35M },
	{ 0, ~0 },
};

/* The sun8i clk_csr_i to GMII_Address CR field mapping uses rate as the
 * exclusive minimum frequency for the divisor. Note that the last entry
 * is valid and also acts as the sentinel.
 */
static const struct stmmac_clk_rate stmmac_sun8i_csr_to_mdc[] = {
	{ 160000000, 3 },
	{ 80000000, 2 },
	{ 40000000, 1 },
	{ 0, 0 },
};

/* The xgmac clk_csr_i to GMII_Address CR field mapping similarly uses rate
 * as the exclusive minimum frequency for the divisor, and again the last
 * entry is valid and also the sentinel.
 */
static const struct stmmac_clk_rate stmmac_xgmac_csr_to_mdc[] = {
	{ 400000000, 5 },
	{ 350000000, 4 },
	{ 300000000, 3 },
	{ 250000000, 2 },
	{ 150000000, 1 },
	{ 0, 0 },
};

/**
 * stmmac_clk_csr_set - dynamically set the MDC clock
 * @priv: driver private structure
 * Description: this is to dynamically set the MDC clock according to the csr
 * clock input.
 * Return: MII register CR field value
 * Note:
 *	If a specific clk_csr value is passed from the platform
 *	this means that the CSR Clock Range selection cannot be
 *	changed at run-time and it is fixed (as reported in the driver
 *	documentation). Vice versa the driver will try to set the MDC
 *	clock dynamically according to the actual clock input.
 */
static u32 stmmac_clk_csr_set(struct stmmac_priv *priv)
{
	const struct stmmac_clk_rate *rates;
	unsigned long clk_rate;
	u32 value = ~0;
	int i;

	clk_rate = clk_get_rate(priv->plat->stmmac_clk);

	/* Platform provided default clk_csr would be assumed valid
	 * for all other cases except for the below mentioned ones.
	 * For values higher than the IEEE 802.3 specified frequency
	 * we can not estimate the proper divider as it is not known
	 * the frequency of clk_csr_i. So we do not change the default
	 * divider.
	 */
	rates = stmmac_std_csr_to_mdc;
	if (priv->plat->flags & STMMAC_FLAG_HAS_SUN8I)
		rates = stmmac_sun8i_csr_to_mdc;
	if (priv->plat->core_type == DWMAC_CORE_XGMAC)
		rates = stmmac_xgmac_csr_to_mdc;

	for (i = 0; rates[i].rate; i++)
		if (clk_rate > rates[i].rate)
			break;
	if (rates[i].cr != (u8)~0)
		value = rates[i].cr;

	return value;
}

Annotation

Implementation Notes