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
{
unsigned long clk_rate;
u32 value = ~0;
+ int i;
clk_rate = clk_get_rate(priv->plat->stmmac_clk);
* 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;