diff options
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 8 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/hwif.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 60 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 2 | ||||
-rw-r--r-- | drivers/net/phy/phylink.c | 18 | ||||
-rw-r--r-- | include/linux/phylink.h | 2 | ||||
-rw-r--r-- | include/linux/stmmac.h | 2 |
9 files changed, 70 insertions, 39 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index 03b1c5a97826..c6ff1fa0e04d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -68,6 +68,11 @@ static void dwmac4_core_init(struct mac_device_info *hw, init_waitqueue_head(&priv->tstamp_busy_wait); } +static void dwmac4_phylink_get_caps(struct stmmac_priv *priv) +{ + priv->phylink_config.mac_capabilities |= MAC_2500FD; +} + static void dwmac4_rx_queue_enable(struct mac_device_info *hw, u8 mode, u32 queue) { @@ -1131,6 +1136,7 @@ static int dwmac4_config_l4_filter(struct mac_device_info *hw, u32 filter_no, const struct stmmac_ops dwmac4_ops = { .core_init = dwmac4_core_init, + .phylink_get_caps = dwmac4_phylink_get_caps, .set_mac = stmmac_set_mac, .rx_ipc = dwmac4_rx_ipc_enable, .rx_queue_enable = dwmac4_rx_queue_enable, @@ -1173,6 +1179,7 @@ const struct stmmac_ops dwmac4_ops = { const struct stmmac_ops dwmac410_ops = { .core_init = dwmac4_core_init, + .phylink_get_caps = dwmac4_phylink_get_caps, .set_mac = stmmac_dwmac4_set_mac, .rx_ipc = dwmac4_rx_ipc_enable, .rx_queue_enable = dwmac4_rx_queue_enable, @@ -1221,6 +1228,7 @@ const struct stmmac_ops dwmac410_ops = { const struct stmmac_ops dwmac510_ops = { .core_init = dwmac4_core_init, + .phylink_get_caps = dwmac4_phylink_get_caps, .set_mac = stmmac_dwmac4_set_mac, .rx_ipc = dwmac4_rx_ipc_enable, .rx_queue_enable = dwmac4_rx_queue_enable, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index 34e1b0c3f346..f352be269deb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -47,6 +47,14 @@ static void dwxgmac2_core_init(struct mac_device_info *hw, writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN); } +static void xgmac_phylink_get_caps(struct stmmac_priv *priv) +{ + priv->phylink_config.mac_capabilities |= MAC_2500FD | MAC_5000FD | + MAC_10000FD | MAC_25000FD | + MAC_40000FD | MAC_50000FD | + MAC_100000FD; +} + static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable) { u32 tx = readl(ioaddr + XGMAC_TX_CONFIG); @@ -1490,6 +1498,7 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, u32 num_txq, const struct stmmac_ops dwxgmac210_ops = { .core_init = dwxgmac2_core_init, + .phylink_get_caps = xgmac_phylink_get_caps, .set_mac = dwxgmac2_set_mac, .rx_ipc = dwxgmac2_rx_ipc, .rx_queue_enable = dwxgmac2_rx_queue_enable, @@ -1551,6 +1560,7 @@ static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode, const struct stmmac_ops dwxlgmac2_ops = { .core_init = dwxgmac2_core_init, + .phylink_get_caps = xgmac_phylink_get_caps, .set_mac = dwxgmac2_set_mac, .rx_ipc = dwxgmac2_rx_ipc, .rx_queue_enable = dwxlgmac2_rx_queue_enable, diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 238f17c50a1e..b95d3e137813 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -300,6 +300,8 @@ struct stmmac_est; struct stmmac_ops { /* MAC core initialization */ void (*core_init)(struct mac_device_info *hw, struct net_device *dev); + /* Get phylink capabilities */ + void (*phylink_get_caps)(struct stmmac_priv *priv); /* Enable the MAC RX/TX */ void (*set_mac)(void __iomem *ioaddr, bool enable); /* Enable and verify that the IPC module is supported */ @@ -419,6 +421,8 @@ struct stmmac_ops { #define stmmac_core_init(__priv, __args...) \ stmmac_do_void_callback(__priv, mac, core_init, __args) +#define stmmac_mac_phylink_get_caps(__priv) \ + stmmac_do_void_callback(__priv, mac, phylink_get_caps, __priv) #define stmmac_mac_set(__priv, __args...) \ stmmac_do_void_callback(__priv, mac, set_mac, __args) #define stmmac_rx_ipc(__priv, __args...) \ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 7a9bbcf03ea5..33ca5c50bdcd 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1153,7 +1153,7 @@ static int stmmac_init_phy(struct net_device *dev) if (!phylink_expects_phy(priv->phylink)) return 0; - fwnode = of_fwnode_handle(priv->plat->phylink_node); + fwnode = priv->plat->port_node; if (!fwnode) fwnode = dev_fwnode(priv->device); @@ -1199,21 +1199,21 @@ static int stmmac_init_phy(struct net_device *dev) static int stmmac_phy_setup(struct stmmac_priv *priv) { - struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; - struct fwnode_handle *fwnode = of_fwnode_handle(priv->plat->phylink_node); - int max_speed = priv->plat->max_speed; + struct stmmac_mdio_bus_data *mdio_bus_data; int mode = priv->plat->phy_interface; + struct fwnode_handle *fwnode; struct phylink *phylink; + int max_speed; priv->phylink_config.dev = &priv->dev->dev; priv->phylink_config.type = PHYLINK_NETDEV; - if (priv->plat->mdio_bus_data) + priv->phylink_config.mac_managed_pm = true; + + mdio_bus_data = priv->plat->mdio_bus_data; + if (mdio_bus_data) priv->phylink_config.ovr_an_inband = mdio_bus_data->xpcs_an_inband; - if (!fwnode) - fwnode = dev_fwnode(priv->device); - /* Set the platform/firmware specified interface mode */ __set_bit(mode, priv->phylink_config.supported_interfaces); @@ -1223,36 +1223,24 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) priv->phylink_config.supported_interfaces); priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | - MAC_10 | MAC_100; - - if (!max_speed || max_speed >= 1000) - priv->phylink_config.mac_capabilities |= MAC_1000; - - if (priv->plat->has_gmac4) { - if (!max_speed || max_speed >= 2500) - priv->phylink_config.mac_capabilities |= MAC_2500FD; - } else if (priv->plat->has_xgmac) { - if (!max_speed || max_speed >= 2500) - priv->phylink_config.mac_capabilities |= MAC_2500FD; - if (!max_speed || max_speed >= 5000) - priv->phylink_config.mac_capabilities |= MAC_5000FD; - if (!max_speed || max_speed >= 10000) - priv->phylink_config.mac_capabilities |= MAC_10000FD; - if (!max_speed || max_speed >= 25000) - priv->phylink_config.mac_capabilities |= MAC_25000FD; - if (!max_speed || max_speed >= 40000) - priv->phylink_config.mac_capabilities |= MAC_40000FD; - if (!max_speed || max_speed >= 50000) - priv->phylink_config.mac_capabilities |= MAC_50000FD; - if (!max_speed || max_speed >= 100000) - priv->phylink_config.mac_capabilities |= MAC_100000FD; - } + MAC_10FD | MAC_100FD | + MAC_1000FD; /* Half-Duplex can only work with single queue */ - if (priv->plat->tx_queues_to_use > 1) - priv->phylink_config.mac_capabilities &= - ~(MAC_10HD | MAC_100HD | MAC_1000HD); - priv->phylink_config.mac_managed_pm = true; + if (priv->plat->tx_queues_to_use <= 1) + priv->phylink_config.mac_capabilities |= MAC_10HD | MAC_100HD | + MAC_1000HD; + + /* Get the MAC specific capabilities */ + stmmac_mac_phylink_get_caps(priv); + + max_speed = priv->plat->max_speed; + if (max_speed) + phylink_limit_mac_speed(&priv->phylink_config, max_speed); + + fwnode = priv->plat->port_node; + if (!fwnode) + fwnode = dev_fwnode(priv->device); phylink = phylink_create(&priv->phylink_config, fwnode, mode, &stmmac_phylink_mac_ops); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index dd9e2fec5328..fa9e7e7040b9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -533,11 +533,11 @@ int stmmac_mdio_register(struct net_device *ndev) int err = 0; struct mii_bus *new_bus; struct stmmac_priv *priv = netdev_priv(ndev); - struct fwnode_handle *fwnode = of_fwnode_handle(priv->plat->phylink_node); struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; struct device_node *mdio_node = priv->plat->mdio_node; struct device *dev = ndev->dev.parent; struct fwnode_handle *fixed_node; + struct fwnode_handle *fwnode; int addr, found, max_addr; if (!mdio_bus_data) @@ -601,6 +601,7 @@ int stmmac_mdio_register(struct net_device *ndev) stmmac_xgmac2_mdio_read_c45(new_bus, 0, 0, 0); /* If fixed-link is set, skip PHY scanning */ + fwnode = priv->plat->port_node; if (!fwnode) fwnode = dev_fwnode(priv->device); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index be8e79c7aa34..ff330423ee66 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -428,7 +428,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) plat->phy_node = of_parse_phandle(np, "phy-handle", 0); /* PHYLINK automatically parses the phy-handle property */ - plat->phylink_node = np; + plat->port_node = of_fwnode_handle(np); /* Get max speed of operation from device tree */ of_property_read_u32(np, "max-speed", &plat->max_speed); diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 160bce608c34..0d7354955d62 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -427,6 +427,24 @@ static struct { }; /** + * phylink_limit_mac_speed - limit the phylink_config to a maximum speed + * @config: pointer to a &struct phylink_config + * @max_speed: maximum speed + * + * Mask off MAC capabilities for speeds higher than the @max_speed parameter. + * Any further motifications of config.mac_capabilities will override this. + */ +void phylink_limit_mac_speed(struct phylink_config *config, u32 max_speed) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(phylink_caps_params) && + phylink_caps_params[i].speed > max_speed; i++) + config->mac_capabilities &= ~phylink_caps_params[i].mask; +} +EXPORT_SYMBOL_GPL(phylink_limit_mac_speed); + +/** * phylink_cap_from_speed_duplex - Get mac capability from speed/duplex * @speed: the speed to search for * @duplex: the duplex to search for diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 789c516c6b4a..7d07f8736431 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -223,6 +223,8 @@ struct phylink_config { unsigned long mac_capabilities; }; +void phylink_limit_mac_speed(struct phylink_config *config, u32 max_speed); + /** * struct phylink_mac_ops - MAC operations structure. * @validate: Validate and update the link configuration. diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 784277d666eb..b2ccd827bb80 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -227,7 +227,7 @@ struct plat_stmmacenet_data { phy_interface_t phy_interface; struct stmmac_mdio_bus_data *mdio_bus_data; struct device_node *phy_node; - struct device_node *phylink_node; + struct fwnode_handle *port_node; struct device_node *mdio_node; struct stmmac_dma_cfg *dma_cfg; struct stmmac_est *est; |