diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 42a48f655849..46454e2886ce 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -257,6 +257,7 @@ struct stmmac_safety_stats { (sizeof(struct stmmac_safety_stats) / sizeof(unsigned long)) /* CSR Frequency Access Defines*/ +#define CSR_F_20M 20000000 #define CSR_F_35M 35000000 #define CSR_F_60M 60000000 #define CSR_F_100M 100000000 @@ -607,12 +608,9 @@ struct mac_link { struct mii_regs { unsigned int addr; /* MII Address */ unsigned int data; /* MII Data */ - unsigned int addr_shift; /* MII address shift */ - unsigned int reg_shift; /* MII reg shift */ - unsigned int addr_mask; /* MII address mask */ - unsigned int reg_mask; /* MII reg mask */ - unsigned int clk_csr_shift; - unsigned int clk_csr_mask; + u32 addr_mask; /* MII address mask */ + u32 reg_mask; /* MII reg mask */ + u32 clk_csr_mask; }; struct mac_device_info { diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index ece2a0c38562..fc13bfb47783 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -699,7 +699,7 @@ static int intel_mgbe_common_data(struct pci_dev *pdev, /* Intel mgbe SGMII interface uses pcs-xcps */ if (plat->phy_interface == PHY_INTERFACE_MODE_SGMII || plat->phy_interface == PHY_INTERFACE_MODE_1000BASEX) { - plat->mdio_bus_data->pcs_mask = BIT(INTEL_MGBE_XPCS_ADDR); + plat->mdio_bus_data->pcs_mask = BIT_U32(INTEL_MGBE_XPCS_ADDR); plat->mdio_bus_data->default_an_inband = true; plat->select_pcs = intel_mgbe_select_pcs; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 9c51c96223ad..ada6c6ef1f5c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -168,7 +168,7 @@ static int loongson_gnet_data(struct pci_dev *pdev, loongson_default_data(pdev, plat); plat->phy_interface = PHY_INTERFACE_MODE_GMII; - plat->mdio_bus_data->phy_mask = ~(u32)BIT(2); + plat->mdio_bus_data->phy_mask = ~BIT_U32(2); plat->fix_mac_speed = loongson_gnet_fix_speed; return 0; @@ -367,12 +367,9 @@ static int loongson_dwmac_setup(void *apriv, struct mac_device_info *mac) mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES; mac->mii.addr = GMAC_MII_ADDR; mac->mii.data = GMAC_MII_DATA; - mac->mii.addr_shift = 11; - mac->mii.addr_mask = 0x0000F800; - mac->mii.reg_shift = 6; - mac->mii.reg_mask = 0x000007C0; - mac->mii.clk_csr_shift = 2; - mac->mii.clk_csr_mask = GENMASK(5, 2); + mac->mii.addr_mask = GENMASK_U32(15, 11); + mac->mii.reg_mask = GENMASK_U32(10, 6); + mac->mii.clk_csr_mask = GENMASK_U32(5, 2); return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index c01b86fd64da..3ce03b059277 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -1063,12 +1063,9 @@ static int sun8i_dwmac_setup(void *ppriv, struct mac_device_info *mac) mac->link.duplex = EMAC_DUPLEX_FULL; mac->mii.addr = EMAC_MDIO_CMD; mac->mii.data = EMAC_MDIO_DATA; - mac->mii.reg_shift = 4; - mac->mii.reg_mask = GENMASK(8, 4); - mac->mii.addr_shift = 12; - mac->mii.addr_mask = GENMASK(16, 12); - mac->mii.clk_csr_shift = 20; - mac->mii.clk_csr_mask = GENMASK(22, 20); + mac->mii.reg_mask = GENMASK_U32(8, 4); + mac->mii.addr_mask = GENMASK_U32(16, 12); + mac->mii.clk_csr_mask = GENMASK_U32(22, 20); mac->unicast_filter_entries = 8; /* Synopsys Id is not available */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index af566636fad9..c7cb30672604 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -496,12 +496,9 @@ int dwmac1000_setup(struct stmmac_priv *priv) mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES; mac->mii.addr = GMAC_MII_ADDR; mac->mii.data = GMAC_MII_DATA; - mac->mii.addr_shift = 11; - mac->mii.addr_mask = 0x0000F800; - mac->mii.reg_shift = 6; - mac->mii.reg_mask = 0x000007C0; - mac->mii.clk_csr_shift = 2; - mac->mii.clk_csr_mask = GENMASK(5, 2); + mac->mii.addr_mask = GENMASK_U32(15, 11); + mac->mii.reg_mask = GENMASK_U32(10, 6); + mac->mii.clk_csr_mask = GENMASK_U32(5, 2); return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c index db4fbe64a38a..6b5cf3a0866a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c @@ -184,12 +184,9 @@ int dwmac100_setup(struct stmmac_priv *priv) mac->link.speed_mask = MAC_CONTROL_PS; mac->mii.addr = MAC_MII_ADDR; mac->mii.data = MAC_MII_DATA; - mac->mii.addr_shift = 11; - mac->mii.addr_mask = 0x0000F800; - mac->mii.reg_shift = 6; - mac->mii.reg_mask = 0x000007C0; - mac->mii.clk_csr_shift = 2; - mac->mii.clk_csr_mask = GENMASK(5, 2); + mac->mii.addr_mask = GENMASK_U32(15, 11); + mac->mii.reg_mask = GENMASK_U32(10, 6); + mac->mii.clk_csr_mask = GENMASK_U32(5, 2); return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index 623868afe93d..602771e19d0f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -1030,12 +1030,9 @@ int dwmac4_setup(struct stmmac_priv *priv) mac->link.speed_mask = GMAC_CONFIG_FES | GMAC_CONFIG_PS; mac->mii.addr = GMAC_MDIO_ADDR; mac->mii.data = GMAC_MDIO_DATA; - mac->mii.addr_shift = 21; - mac->mii.addr_mask = GENMASK(25, 21); - mac->mii.reg_shift = 16; - mac->mii.reg_mask = GENMASK(20, 16); - mac->mii.clk_csr_shift = 8; - mac->mii.clk_csr_mask = GENMASK(11, 8); + mac->mii.addr_mask = GENMASK_U32(25, 21); + mac->mii.reg_mask = GENMASK_U32(20, 16); + mac->mii.clk_csr_mask = GENMASK_U32(11, 8); mac->num_vlan = stmmac_get_num_vlan(priv->ioaddr); return 0; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index 49893b9fb88c..915e7c2ab11f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -1551,12 +1551,9 @@ int dwxgmac2_setup(struct stmmac_priv *priv) mac->mii.addr = XGMAC_MDIO_ADDR; mac->mii.data = XGMAC_MDIO_DATA; - mac->mii.addr_shift = 16; - mac->mii.addr_mask = GENMASK(20, 16); - mac->mii.reg_shift = 0; - mac->mii.reg_mask = GENMASK(15, 0); - mac->mii.clk_csr_shift = 19; - mac->mii.clk_csr_mask = GENMASK(21, 19); + mac->mii.addr_mask = GENMASK_U32(20, 16); + mac->mii.reg_mask = GENMASK_U32(15, 0); + mac->mii.clk_csr_mask = GENMASK_U32(21, 19); mac->num_vlan = stmmac_get_num_vlan(priv->ioaddr); return 0; @@ -1594,12 +1591,9 @@ int dwxlgmac2_setup(struct stmmac_priv *priv) mac->mii.addr = XGMAC_MDIO_ADDR; mac->mii.data = XGMAC_MDIO_DATA; - mac->mii.addr_shift = 16; - mac->mii.addr_mask = GENMASK(20, 16); - mac->mii.reg_shift = 0; - mac->mii.reg_mask = GENMASK(15, 0); - mac->mii.clk_csr_shift = 19; - mac->mii.clk_csr_mask = GENMASK(21, 19); + mac->mii.addr_mask = GENMASK_U32(20, 16); + mac->mii.reg_mask = GENMASK_U32(15, 0); + mac->mii.clk_csr_mask = GENMASK_U32(21, 19); return 0; } diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 485a0d790baa..afe98ff5bdcb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -234,8 +234,8 @@ static u32 stmmac_mdio_format_addr(struct stmmac_priv *priv, { const struct mii_regs *mii_regs = &priv->hw->mii; - return ((pa << mii_regs->addr_shift) & mii_regs->addr_mask) | - ((gr << mii_regs->reg_shift) & mii_regs->reg_mask) | + return field_prep(mii_regs->addr_mask, pa) | + field_prep(mii_regs->reg_mask, gr) | priv->gmii_address_bus_config | MII_ADDR_GBUSY; } @@ -473,6 +473,53 @@ 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_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 @@ -488,8 +535,10 @@ void stmmac_pcs_clean(struct net_device *ndev) */ 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); @@ -500,48 +549,17 @@ 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; + 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; - 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; - } - - 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; - } + 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; } @@ -559,7 +577,7 @@ static void stmmac_mdio_bus_config(struct stmmac_priv *priv) else value = stmmac_clk_csr_set(priv); - value <<= priv->hw->mii.clk_csr_shift; + value <<= __ffs(priv->hw->mii.clk_csr_mask); if (value & ~priv->hw->mii.clk_csr_mask) dev_warn(priv->device, diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 2fc169c7117e..965ada809fdf 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -84,12 +84,12 @@ struct stmmac_priv; /* Platfrom data for platform device structure's platform_data field */ struct stmmac_mdio_bus_data { - unsigned int phy_mask; - unsigned int pcs_mask; - unsigned int default_an_inband; + u32 phy_mask; + u32 pcs_mask; int *irqs; int probed_phy_irq; bool needs_reset; + bool default_an_inband; }; struct stmmac_dma_cfg {