diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 485a0d790baa..c4123d2260bd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -473,6 +473,52 @@ void stmmac_pcs_clean(struct net_device *ndev) priv->hw->xpcs = NULL; } +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_35M, STMMAC_CSR_20_35M }, + { CSR_F_60M, STMMAC_CSR_35_60M }, + { CSR_F_100M, STMMAC_CSR_60_100M }, + { CSR_F_150M, STMMAC_CSR_100_150M }, + { CSR_F_250M, STMMAC_CSR_150_250M }, + { CSR_F_300M, STMMAC_CSR_250_300M }, + { CSR_F_500M, STMMAC_CSR_300_500M }, + { CSR_F_800M, STMMAC_CSR_500_800M }, + { }, +}; + +/* 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 @@ -490,6 +536,7 @@ static u32 stmmac_clk_csr_set(struct stmmac_priv *priv) { unsigned long clk_rate; u32 value = ~0; + int i; clk_rate = clk_get_rate(priv->plat->stmmac_clk); @@ -500,47 +547,26 @@ static u32 stmmac_clk_csr_set(struct stmmac_priv *priv) * the frequency of clk_csr_i. So we do not change the default * divider. */ - if (clk_rate < CSR_F_35M) - value = STMMAC_CSR_20_35M; - else if (clk_rate < CSR_F_60M) - value = STMMAC_CSR_35_60M; - else if (clk_rate < CSR_F_100M) - value = STMMAC_CSR_60_100M; - else if (clk_rate < CSR_F_150M) - value = STMMAC_CSR_100_150M; - else if (clk_rate < CSR_F_250M) - value = STMMAC_CSR_150_250M; - else if (clk_rate <= CSR_F_300M) - value = STMMAC_CSR_250_300M; - else if (clk_rate < CSR_F_500M) - value = STMMAC_CSR_300_500M; - else if (clk_rate < CSR_F_800M) - value = STMMAC_CSR_500_800M; + for (i = 0; stmmac_std_csr_to_mdc[i].rate; i++) + if (clk_rate < stmmac_std_csr_to_mdc[i].rate) { + value = stmmac_std_csr_to_mdc[i].cr; + break; + } if (priv->plat->flags & STMMAC_FLAG_HAS_SUN8I) { - if (clk_rate > 160000000) - value = 0x03; - else if (clk_rate > 80000000) - value = 0x02; - else if (clk_rate > 40000000) - value = 0x01; - else - value = 0; + /* Note the different test - this is intentional. */ + for (i = 0; stmmac_sun8i_csr_to_mdc[i].rate; i++) + if (clk_rate > stmmac_sun8i_csr_to_mdc[i].rate) + break; + value = stmmac_sun8i_csr_to_mdc[i].cr; } if (priv->plat->core_type == DWMAC_CORE_XGMAC) { - if (clk_rate > 400000000) - value = 0x5; - else if (clk_rate > 350000000) - value = 0x4; - else if (clk_rate > 300000000) - value = 0x3; - else if (clk_rate > 250000000) - value = 0x2; - else if (clk_rate > 150000000) - value = 0x1; - else - value = 0x0; + /* Note the different test - this is intentional. */ + for (i = 0; stmmac_xgmac_csr_to_mdc[i].rate; i++) + if (clk_rate > stmmac_xgmac_csr_to_mdc[i].rate) + break; + value = stmmac_xgmac_csr_to_mdc[i].cr; } return value;